2017-08-25 2 views
3

J'ai un équivalent à std::integer_sequence (nous n'utilisons pas encore le C++ 14). J'ai aussi deux classes auxiliaires qui suppriment ou ajoutent un nombre principal.spécialisation partielle du modèle Variadic "pas plus spécialisé" en g ++ 7.1.1

// Sequence type  
template <typename Type, Type ... Values>          
struct Sequence                
{                    
    using value_type = Type;             
};                   

// Pop a value off of the start of a sequence         
template <class Class>              
struct SequencePop;               

template <typename Type, Type Value, Type ... Values>       
struct SequencePop<Sequence<Type, Value, Values ...>>       
{                            
    using type = Sequence<Type, Values ...>;         
};                   

// Push a value on to the start of a sequence         
template <class Class, typename Class::value_type Value>      
struct SequencePush;               

template <typename Type, Type Value, Type ... Values>       
struct SequencePush<Sequence<Type, Values ...>, Value>      
{                    
    using type = Sequence<Type, Value, Values ...>;       
};                   

SequencePop est considéré comme valable dans tous les compilateurs J'ai essayé (g ++ 6.4.1, g ++ 7.1.1, clang ++ 4.0.1). SequencePush ne compile pas avec g ++ 7.1.1. Le message d'erreur est le suivant.

test.cpp:24:8: error: partial specialization ‘struct SequencePush<Sequence<Type, Values ...>, Value>’ is not more specialized than [-fpermissive] 
struct SequencePush<Sequence<Type, Values ...>, Value> 
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
test.cpp:21:8: note: primary template ‘template<class Class, typename Class::value_type Value> struct SequencePush’ 
struct SequencePush; 

est-g ++ 7.1.1 raison de rejeter ce code, et si oui, comment peut-on dire que SequencePush n'est pas « plus spécialisé » que le modèle primaire?

Répondre

2

Il devrait être

template <typename Type, 
      Type ... Values, 
      typename Sequence<Type, Values ...>::value_type Value> 
struct SequencePush<Sequence<Type, Values ...>, Value> 
{ 
    using type = Sequence<Type, Value, Values ...>; 
}; 

Demo

comme Class::value_type et Type de Sequence<Type, Values ...> ne sont pas "liés".

+0

Bien que cela fonctionne, je ne comprends pas pourquoi le code d'origine OP ne compilerait pas. À tout le moins, la spécialisation partielle devrait être plus spécialisée car elle inclut une classe de modèle de modèle 'Sequence'. Qu'est-ce que je rate? – Curious

+0

C'est beaucoup mieux que ma tentative :) – YSC

+1

@Curious: Pas sûr du libellé correct, mais 'Type' n'est pas plus spécialisé que' Class :: value_type' (même s'il est contraint par 'Sequence'). – Jarod42

0

En effet, le modèle général SequencePush est paramétré par un paramètre de modèle (Class) mais votre spécialisation est paramétrés par deux (Type et Value). Dans le modèle général, Type n'est pas un paramètre car il est déduit de Class.

Un travail mais pas de solution satisfaisante serait:

template <class Class, typename Type, Type Value>      
struct SequencePush;               

template <typename Type, Type Value, Type ... Values>       
struct SequencePush<Sequence<Type, Values ...>, Type, Value>      
{                    
    using type = Sequence<Type, Value, Values ...>;       
};  

demo

+0

La réponse de Jarod42 est toujours paramétrée par Type et Valeur? – Bill