Question

continue mon voyage dans le monde des modèles variadique , j'ai rencontré un autre problème.

En supposant que la classe modèle suivant:

template < typename T >
struct foo 
{
    //default implementation
};

il est possible de se spécialiser en partie pour modèle variadique instanciations comme ceci:

template < template < typename ... > class T, typename ...Args >
struct foo< T< Args... > >
{
    //specialized implementation
};

Avec cela, foo< int > correspond à l'implémentation par défaut et foo< std::tuple< int, char > > à la mise en œuvre spécialisée.

Cependant, les choses se compliquent lorsque vous utilisez plusieurs paramètres du modèle. Par exemple, si nous avons la classe modèle suivant

template < typename T, typename U >
struct bar {};

et nous voulons spécialiser en partie comme nous l'avons fait pour foo, nous ne pouvons pas faire

template < template < typename ... > class T, typename ...TArgs,
           template < typename ... > class U, typename ...UArgs >
struct bar< T< TArgs... >, U< UArgs... > > {};

//This would correspond to the specialized version with
//T=std::tuple,
//TArgs=int,char
//U=std::tuple,
//UArgs=float
bar< std::tuple< int, char >, std::tuple< float > > b;

En effet, si je ne me trompe pas, nous ne pouvons avoir un paquet de paramètres de modèle et il doit être placé à la fin de la liste des paramètres. Je comprends pourquoi cela est obligatoire dans les déclarations de modèle, mais certaine spécialisation de modèle partiel (comme dans l'exemple ci-dessus), cela ne devrait pas être un problème.

Est-il possible d'obtenir une spécialisation de modèle partiel avec plusieurs packs de paramètres de modèle?


Modifier : Maintenant, je me sens stupide ... le code que j'ai donné ci-dessus compiles parfaitement (au moins avec gcc 4.5). L'erreur de compilation que j'avais été pas à cause de paquets de paramètres multiples, mais en raison de leur utilisation comme fonctions membres paramètres. Dans la spécialisation partielle de bar, j'essayé de définir une fonction membre qui prend les deux paramètres de TArgs et UArgs:

template < template < typename ... > class T, typename ...TArgs, 
           template < typename ... > class U, typename ...UArgs >
struct bar< T< TArgs... >, U< UArgs... > >
{
    void method( TArgs... targs, UArgs... uargs ) //compile error here
    {
    }
};

Sur la déclaration de fonction membre, gcc me donne l'erreur

  

paquets de paramètres doivent être à la fin de la liste des paramètres.

Pour autant que je peux dire, le compilateur doit être en mesure de définir la fonction de membre correct pour un modèle donné instanciation, par exemple bar< std::tuple< int, char >, std::tuple< float > > doit contenir une fonction membre void method( int, char, float ). Est-ce que je fais quelque chose de mal? Ou suis-je en train de faire quelque chose qui est impossible? Si oui, est-il une bonne raison pour laquelle cela est impossible?

Était-ce utile?

La solution

Probablement cette réponse ne supprimera pas directement à votre question, mais le code suivant compilé sur ideone (gcc-4.5.1) quand je l'ai testé.

#include <cstdio>
#include <tuple>

template< class, class > struct S {
  S() { puts("primary"); }
};

template<
  template< class... > class T, class...TArgs
, template< class... > class U, class...UArgs
>
struct S< T< TArgs... >, U< UArgs... > > {
  S() { puts("specialized"); }
};

int main()
{
  S< int, int >  p;                                       // "primary"
  S< std::tuple< int, char >, std::tuple< float > >  s;   // "specialised"
}

Je ne suis pas sûr que ce code est strictement conforme, mais pour autant que je lis N3225 14.5.3, je ne pouvais pas trouver la déclaration qui mentionne ce pack de paramètre de modèle doit être le dernier paramètre de modèle.

Edit:
Je relis N3225 et a trouvé les déclarations suivantes:

  

8.3.5 / 4 Si le paramètre-déclaration article   se termine par une ellipse ou un   Pack paramètre de fonction (14.5.3), le   nombre d'arguments est égal à   ou supérieur au nombre de   les paramètres qui ne disposent pas d'un défaut   l'argument et ne sont pas fonction   les paquets de paramètres.

     

14.8.2.5/10 [Note: Un pack de paramètre de fonction ne peut se produire à la   fin d'une   paramètre-declarationlist (8.3.5). -fin   ndlr]

Donc, comme vous l'avez mentionné, pack paramètre de fonction doit être le dernier paramètre malheureusement.
Une fonction membre non-modèle d'un modèle de classe est une fonction ordinaire pour cette classe quand il est instancié (entièrement spécialisée). Je souhaite donc que le code de cette question peut être compilé logiquement, comme cas particulier.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top