Fait une spécialisation de modèle de fonction juridique virtuelle?
-
09-09-2019 - |
Question
En C ++, une spécialisation de modèle de fonction est censé agir exactement comme une fonction normale. Est-ce que cela signifie que je peux faire un? Virtuel
Par exemple:
struct A
{
template <class T> void f();
template <> virtual void f<int>() {}
};
struct B : A
{
template <class T> void f();
template <> virtual void f<int>() {}
};
int main(int argc, char* argv[])
{
B b;
A& a = b;
a.f<int>();
}
Visual Studio 2005 me donne l'erreur suivante:
erreur fatale C1001:. Une erreur interne est produite dans le compilateur
La solution
Nice erreur du compilateur. Pour ce type de contrôles que je REPLI toujours Comeau compilateur avant de retourner à la norme et la vérification.
Comeau C / C ++ 4.3.10.1 (6 octobre 2008 11:28:09) pour ONLINE_EVALUATION_BETA2 Droit d'auteur 1988-2008 Comeau Computing. Tous les droits sont réservés. MODE: stricte erreurs C ++ C ++ 0x_extensions
"ComeauTest.c", ligne 3: Erreur: « Virtuelle » n'est pas autorisé dans une fonction modèle déclaration virtual void modèle f (); ^
"ComeauTest.c", ligne 10: Erreur: « Virtuelle » n'est pas autorisé dans une fonction modèle déclaration virtual void modèle f (); ^
Maintenant, comme il a été posté par un autre utilisateur, le fait est que la norme ne vous permet pas de définir des méthodes virtuelles templated. La raison est que pour toutes les méthodes virtuelles, une entrée doit être réservé à la vtable. Le problème est que les méthodes de modèle ne seront définis quand ils ont été instancié (utilisé). Cela signifie que le vtable finirait par avoir un nombre différent d'éléments dans chaque unité de compilation, selon le nombre de différents appels à f () avec différents types se produisent. Puis l'enfer serait soulevée ...
Si ce que vous voulez est une fonction sur l'un basé sur un modèle ses arguments et une version spécifique étant virtuelle (note de la part de l'argument), vous pouvez le faire:
class Base
{
public:
template <typename T> void f( T a ) {}
virtual void f( int a ) { std::cout << "base" << std::endl; }
};
class Derived : public Base
{
public:
virtual void f( int a ) { std::cout << "derived" << std::endl; }
};
int main()
{
Derived d;
Base& b = d;
b.f( 5 ); // The compiler will prefer the non-templated method and print "derived"
}
Si vous voulez que cette généralisée pour tout type, alors vous êtes hors de la chance. Prenons un autre type de délégation au lieu de polymorphisme (agrégation + délégation pourrait être une solution). Plus d'informations sur le problème à portée de main contribuerait à déterminer une solution.
Autres conseils
Selon http://www.kuzbass.ru:8086/docs /isocpp/template.html ISO / CEI 14882: 1998:
-3- Un modèle de fonction membre ne doit pas être virtuel.
Exemple:
template <class T> struct AA {
template <class C> virtual void g(C); // Error
virtual void f(); // OK
};
Comme d'autres l'ont noté, ce n'est pas un code juridique, car un modèle de fonction de membre ne peut être déclarée virtual
.
Pourtant, même Studio 2012 de Visual selfs à ce sujet: Cliquez ici pour la taille complète
Les journaux d'événements indiquent que le compilateur est écrasé sur 0xC0000005
ou STATUS_ACCESS_VIOLATION
. Il est drôle comment une certaine construction de code (illégal) peut rendre le compilateur segfault ...