2010-01-19 7 views
29

J'ai le code qui fonctionne dans VC9 (Microsoft Visual C++ 2008 SP1) mais pas dans GCC 4.2 (sur Mac):Syntaxe C++ pour la spécialisation explicite d'une fonction de modèle dans une classe de modèle?

struct tag {}; 

template< typename T > 
struct C 
{ 
    template< typename Tag > 
    void f(T);     // declaration only 

    template<> 
    inline void f<tag>(T) {} // ERROR: explicit specialization in 
};        // non-namespace scope 'structC<T>' 

Je comprends que GCC voudrait que je déplacer ma spécialisation explicite en dehors de la classe, mais je ne peut pas comprendre la syntaxe. Des idées?

// the following is not correct syntax, what is? 
template< typename T > 
template<> 
inline void C<T>::f<tag>(T) {} 

Répondre

26

Vous ne pouvez pas spécialiser une fonction membre sans spécialiser explicitement la classe conteneur.
Ce que vous pouvez faire est cependant de transférer les appels à une fonction de membre d'un type partiellement spécialisé:

template<class T, class Tag> 
struct helper { 
    static void f(T); 
}; 

template<class T> 
struct helper<T, tag1> { 
    static void f(T) {} 
}; 

template<class T> 
struct C { 
    // ... 
    template<class Tag> 
    void foo(T t) { 
     helper<T, Tag>::f(t); 
    } 
}; 
+0

Ceci est similaire à la solution que j'utilise, merci! Je me demande s'il existe un moyen de le faire de façon moins verbeuse en utilisant Boost? – jwfearn

+0

Pas vraiment, ça ne devient pas plus facile en général. Vous avez besoin d'une fonction d'assistance pour éviter que * "la classe englobante doive être explicitement spécialisée" * et vous devez déplacer celle-ci dans une classe pour faire une spécialisation partielle. –

1

Essayez ceci:

template <> template<typename T> inline void C<T> :: foo<tag2>(T) {} 
+0

Nope, qui ne regrette fonctionne pas – jwfearn

+0

- Je pense que je mélange l'ordre de THW deux qualificatifs de modèle. Essayez de placer celui avec les supports vides tout à fait à gauche. –

+0

nope (erreur: spécialisation partielle du modèle non autorisée) 'foo jwfearn

0

Je sais que cela peut ne pas vous satisfaire, mais je ne crois pas que vous ne pouvez pas avoir une spécialisation enfermée dans une structure non explicitement spécialisée.

template<> 
template<> 
inline void C<tag1>::foo<tag2>(t_type) {} 
8

GCC est en clair, ici. MSVC a une extension non standard qui permet une spécialisation en classe. La norme, cependant, dit:

14.7.3.2:
2. An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member. An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member.

De plus, vous ne pouvez pas spécialiser partiellement une fonction. (Bien que je ne suis pas sûr au sujet des détails dans votre cas, ce serait le coup final.)

Vous pouvez faire:

#include <iostream> 

struct true_type {}; 
struct false_type {}; 

template <typename T, typename U> 
struct is_same : false_type 
{ 
    static const bool value = false; 
}; 

template <typename T> 
struct is_same<T, T> : true_type 
{ 
    static const bool value = true; 
}; 

struct tag1 {}; 
struct tag2 {}; 

template< typename T > 
struct C 
{ 
    typedef T t_type; 

    template< typename Tag > 
    void foo(t_type pX) 
    { 
     foo_detail(pX, is_same<Tag, tag1>()); 
    } 

private: 
    void foo_detail(t_type, const true_type&) 
    { 
     std::cout << "In tag1 version." << std::endl; 
    } 
    void foo_detail(t_type, const false_type&) 
    { 
     std::cout << "In not tag1 version." << std::endl; 
    } 
}; 

int main(void) 
{ 
    C<int> c; 
    c.foo<tag1>(int()); 
    c.foo<tag2>(int()); 
    c.foo<double>(int()); 
} 

Bien que ce soit un peu laid.

+4

Peut-être que c'est le standard C++ qui n'est pas en clair ... Si Microsoft peut le faire, pourquoi pas les autres compilateurs? –

Questions connexes