2

J'ai du mal à comprendre le code suivantspécialisation de modèle avec la liste des paramètres du modèle non vide

template <typename T> 
struct function_traits 
    : public function_traits<decltype(&T::operator())> 
{}; 
// For generic types, directly use the result of the signature of its 'operator()' 

template <typename ClassType, typename ReturnType, typename... Args> 
struct function_traits<ReturnType(ClassType::*)(Args...) const> 
// we specialize for pointers to member function 
{ 
    // ... 
} 

int main() 
{ 
    auto lambda = [](int i) { return long(i*10); }; 

    typedef function_traits<decltype(lambda)> traits; 

    // ... 

    return 0; 
} 

qui se produit dans la réponse https://stackoverflow.com/a/7943765/7006673.

Ici,

template <typename ClassType, typename ReturnType, typename... Args> 
struct function_traits<ReturnType(ClassType::*)(Args...) const> 

semble indiquer une spécialisation de la classe de modèle

template <typename T> 
struct function_traits 

cependant, la liste des paramètres du modèle de la spécialisation template <typename ClassType, typename ReturnType, typename... Args> n'est pas vide (c.-à-n'est pas égal à template <>). Quelqu'un peut-il m'aider s'il vous plaît à comprendre, quel genre de spécialisation c'est et comment les paramètres de modèle ClassType, ReturnType, et Args sont déduits?

Merci beaucoup à l'avance.

Répondre

2

Quel genre de spécialisation est ce?

Ceci est un partial specialization. type_traits est explicitement instancié avec:

T = ReturnType(ClassType::*)(Args...) const 

Mais cette T dépend de ReturnType, ClassType et Args. C'est pourquoi vous n'avez pas template <> dans la déclaration (ce serait un full specialization), mais une déclaration de modèle avec de nouveaux paramètres décrivant un type particulier de T.

Comment sont déduits les paramètres de modèle ClassType, ReturnType et Args?

Elles sont déduites lorsque le modèle est instancié avec une expression qui convient à cette spécialisation. Ici, ReturnType(ClassType::*)(Args...) const ne peut être remplacé par un pointeur vers une méthode.

Ceci est un exemple de SFINAE.

+0

Merci beaucoup. Une question demeure: je pensais que la déduction de type ne peut être faite que pour les paramètres de modèle de fonctions et non pour ceux de structures et de classes - ai-je tort? –

+0

L'instanciation implicite ne peut être faite que pour les paramètres de modèle de fonctions: vous passez explicitement des arguments lors de l'appel de la fonction, de sorte que leurs types peuvent être déduits implicitement. Ici 'function_traits ' est une instanciation explicite avec 'T = decltype (lambda)' – wasthishelpful

+0

Merci! Et la déduction de 'ReturnType',' ClassType' et 'Args' basé sur' decltype (lambda) 'peut être fait puisque' decltype (lambda) 'est un paramètre de template - est-ce exact? –

2

Ceci est une spécialisation partielle. Il ne peut s'agir d'un "rien" comme quelque chose qui prend juste typename T, mais il a encore une certaine variabilité, donc ce n'est pas une spécialisation complète.

En outre, les éléments que vous cherchez à faire correspondre sont le nombre de types dans la ligne de modèle struct/class d'origine et le <...> après le nom dans les spécialisations. C'est un peu bizarre parce que c'est asymétrique.

Dans votre spécialisation partielle:

struct function_traits<ReturnType(ClassType::*)(Args...) const> 

Les trois types combinés toujours créer templated un seul type - un pointeur vers une fonction membre. C'est le même nombre de types que le type de modèle "parent", même si ce type unique est décomposé en 3 types de modèles supplémentaires dans la spécialisation.

// this is what I'm calling the "master template", this isn't an official term 
template<class A, class B, ......., class N> 
class Foo{}; 

template</*...This can have as many (or 0) entries as you need for this specialization...*/> 
class Foo</*...This must have the same number as master template above, but can be broken down into as many smaller pieces as you want...*/> {};