2017-10-11 1 views
2

Prenons le code suivant, qui définit un modèle d'alias pour être passé comme paramètre de modèle de modèle:Passant modèle alias à la classe de base d'un modèle, il dépend de

template<template<class T> class SomeFoo> 
class Base {}; 

template<class T, class Bar> 
class Foo {}; 

class Bar; 

template<class T> 
using BarFoo = Foo<T, Bar>; 

class Bar : public Base<BarFoo> {}; 

Cela fonctionne comme prévu. Cependant, si Bar lui-même est un modèle, cette solution n'est pas possible, car le modèle d'alias dépend de l'instanciation concrète de Bar. La définition du modèle d'alias à l'intérieur de Bar n'aide pas non plus, car elle n'est pas encore disponible lorsque la classe de base est donnée. Comme il ne semble pas être possible de définir le modèle d'alias « à la volée » dans la liste des paramètres, le seul travail autour que je pouvais venir avec est de passer Bar-Base et définir le modèle d'alias là:

template<template<class T, class Derived> class SomeFooTL, class Derived> 
class Base 
{ 
    template<class T> 
    using SomeFoo = SomeFooTL<T, Derived>; 
}; 

template<class T, class Bar> 
class Foo {}; 

template<class S> 
class Bar : public Base<Foo, Bar<S>> {}; 

Ceci est, cependant, très insatisfaisant, car il pourrait y avoir (et sont) d'autres Foo qui ne dépendent de rien mais T et sont maintenant obligés de prendre un second paramètre de template inutile.

Est-ce que quelqu'un sait un meilleur moyen d'y parvenir?

+0

Je ne suis pas sûr de l'avoir, mais vous ne pouvez pas passer une classe dans laquelle vous avez un modèle <...> en utilisant type = ...; au lieu de passer un gabarit? – lorro

+0

@lorro Je pense que je vois ce que vous obtenez, je dois penser à travers ... (BTW Qu'est-ce qui n'est pas clair sur la question? Peut-être que je peux le reformuler.) EDIT: Oui, je pense que ça devrait marcher! Faites-en une réponse appropriée et je l'accepterai. – Knoep

Répondre

2

Si je comprends bien ce que vous voulez, vous avez besoin d'aide, et en utilisant une non syntaxe évidente:

template<template<class> class> 
class Base {}; 

template<class, class> 
class Foo {}; 

template <typename> class Bar; 

template <typename S> struct UsingHelper { 
    template <typename T> 
    using BarFoo = Foo<T, Bar<S>>; 
}; 

template <typename S> 
class Bar : public Base<UsingHelper<S>::template BarFoo> {}; 

template est nécessaire dans UsingHelper<S>::template BarFoo car il est un dépendant du contexte, et il serait « interprété » comme valeur à la place sans. (Il est similaire à typename my_class<T>::type, mais BarFoo est un modèle, pas un type.)

+0

Cela résout très bien! Il est même plus propre que de passer le paramètre du modèle de template dans la classe helper car il ne pollue pas la classe de base. Vous pouvez le rendre encore plus court en demandant à l'outil UsingHelper de prendre Bar directement en tant que paramètre de modèle et de supprimer ainsi la déclaration forward. – Knoep

0

Au lieu de:

template<template<class T> class SomeFoo> 
class Base {}; 

Vous pouvez:

template<class SomeFooT> 
class Base {}; 

Et utiliser SomeFooT::type<T> comme modèle:

struct BarFooT { 
    template<typename T> 
    using type = ...; 
}; 

Ensuite, vous pouvez Prédéclarer struct BarFooT;.

+0

Pouvez-vous être plus précis sur la manière de déclarer BarFooT? (Ou est-ce que je manque quelque chose ici?) – Knoep