2011-04-26 4 views
4

J'ai un modèle de classe, attendant un autre modèle comme paramètre:Passant modèle partiellement spécialisé en tant que paramètre de modèle

template< 
    class Key, 
    template <typename K,template <typename T> class Allocator> class Policy 
> 
class container { 
    Policy<Key,Allocator>* _policy; 
    //some code here 
}; 

et généralement je l'utilise avec la classe politique comme celui-ci:

template <class Key,template <typename T> class Allocator> class policy { 
    //some code 
}; 

mais que faire si je dois passer le paramètre de modèle supplémentaire à la classe de politique? Quelque chose comme:

template <time_t Age,class Key,template <typename T> class Allocator> class policy_3 { 
    //some code 
}; 

Que puis-je faire, pour permettre aux utilisateurs de cette catégorie, passer le paratemeter d'âge sans toucher les autres? Par exemple:

typedef container<key_type,policy_3<100500> > containerWithAge; 
+0

Changer le modèle à un simple 'modèle ' n'est pas une option que je suppose? : P – Xeo

Répondre

7

Vous avez deux options: la liaison et la reliure.

En liaison, vous adaptez la politique ternaire en un binaire, comme prévu par le paramètre modèle-modèle Policy:

template <typename Key, template <typename T> class Allocator> 
struct policy_3_100500 : ternary_policy<100500,Key,Allocator> {}; 

et utiliser policy_3_100500 au lieu de policy_3<100500>.

Pour être plus proche de la syntaxe que vous filmez pour, vous pouvez utiliser une classe imbriquée:

template <time_t Age> 
struct policy_3 { 
    template <typename Key, template <typename T> class Allocator> 
    struct type : ternary_policy<Age,Key,Allocator> {}; 
}; 

et utiliser policy_3<100500>::type au lieu de policy_3<100500>. La seule façon d'obtenir exactement la syntaxe que vous voulez est de déplacer le ::typedans la classe en utilisant la politique. C'est la deuxième option: la reliaison (ceci est aussi utilisé dans std :: allocator, btw). Dans ce cas, vous passez le Policy comme paramètre de modèle normal et assumer un métafonction de modèle, dites bind, d'exister:

template <time_t Age> 
struct policy_3 { 
    template <typename Key, template <typename T> class Allocator> 
    struct bind : ternary_policy<Age,Key,Allocator> {}; 
}; 

Bien identique structurellement à la deuxième option, la différence réside dans qui appelsbind : Dans la première option (liaison), c'est l'utilisateur de la classe de politique (en passant explicitement policy<100500>::type). Ici, il est la classe en utilisant la politique:

template <typename Key, typename Policy> 
struct container { 
    typename Policy::template bind<Key,std::allocator<Key>> * _policy; 
    // ... 
}: 

Comme une note générale, les classes politiques ne sont généralement pas passé comme arguments modèle-modèle, mais comme arguments de modèle normal (précisément parce qu'ils peuvent avoir un nombre variable d'arguments eux-mêmes). Les classes utilisant la politique supposent alors une certaine structure interne (typedefs, fonctions, méta-fonctions, constantes) pour être présentes dans la politique, dont bind n'est qu'un exemple.

+0

Donc, cinq ans plus tard, j'avais exactement le même problème et je suis arrivé à la même solution que vous, mais mon code ne compilait toujours pas avec 'un template de classe attendu, avec X :: type'. Le problème est que je passais 'X :: type' en tant qu'argument dépendant à un autre template, donc la syntaxe correcte était' X :: template type'. Si seulement gcc aurait des messages d'erreur plus utiles. –

Questions connexes