Ou du moins je le pense. Considérez le code suivantCRTP Pourquoi le moteur de recherche de membre est-il en cours d'exécution?
#include <iostream>
#include <memory>
struct BaseBase {
virtual void foo() = 0;
virtual ~BaseBase(){}
};
template <typename Derived>
struct Base : BaseBase{
void foo() override{
static_cast<Derived*>(this)->foo();
}
};
struct D1 : Base<D1> {};
struct Unrelated {};
// no runtime polymorphism
template <typename SDerived>
struct SBase{
void foo() {
static_cast<SDerived*>(this)->foo();
}
};
struct SD1 : SBase<SD1> {};
template <typename T, typename ...Args>
void doFoo(Args&&... args){
T* t = new T(std::forward<Args>(args)...);
t->foo();
}
int main(){
doFoo<Unrelated>(); //compile time error, foo not found in unrelated
doFoo<SD1>(); //runtime crash
doFoo<D1>(); //runtime crash
return 0;
}
J'espérais que le compilateur serait assez gentil pour vérifier l'existence de foo
au moment de la compilation dans doFoo
mais dans les deux cas, avec virtual
dans la base, et sans virtual
dans la base du code compile bien mais se bloque à l'exécution.
Pourquoi est-ce?
Edit: configuration clang
clang version 4.0.1 (tags/RELEASE_401/final)
Target: x86_64-unknown-linux-gnu
avec doFoo<Unrelated>()
commentées compiles.
et g ++ configuration
gcc version 7.1.1 20170630 (GCC)
avec doFoo<Unrelated>()
compile commenté.
Dans son état actuel, je ne pense pas que ce code devrait compiler. Il y a un problème évident avec la définition de 'SD1'. La classe CRTP 'SBase' essaie d'appeler la fonction membre' foo' de 'SDerived'. Mais quand il est instancié avec 'SD1' comme paramètre de modèle, cette fonction membre n'existe pas. Donc, ce programme est mal formé. Je ne pense pas que gcc ou clang compilerait ce programme sans erreurs. Pouvez-vous confirmer que c'est bien le code qui compile et produit un plantage d'exécution? –
@ChrisBeck Lorsque 'SBase :: foo()' est appelé, il essaie en effet d'appeler 'foo' sur le pointeur' SDerived * '. Dans ce cas, 'SDerived' est' SD1'. Et 'SD1' a un membre' foo' qui peut être appelé. Il se trouve être le membre hérité 'SBase :: foo'. –
aschepler
@aschepler: Merci, c'est assez dommage pour l'auteur du code –