g++ 7.1.1 中的可变参数模板偏特化 "not more specialised"

Variadic template partial specialisation "not more specialised" in g++ 7.1.1

我有一个等同于 std::integer_sequence 的函数(我们还没有使用 C++14)。我还有两个助手 类 可以删除或添加前导数字。

// 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 在我尝试过的所有编译器(g++ 6.4.1、g++ 7.1.1、clang++ 4.0.1)中都被认为是有效的。 SequencePush 无法使用 g++ 7.1.1 进行编译。报错信息如下

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;

g++ 7.1.1 拒绝此代码是否正确,如果是,如何判断 SequencePush 不是 "more specialised" 主模板?

应该是

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

因为 Class::value_typeSequence<Type, Values ...> 中的 Type 不是 "related".

确实,通用模板 SequencePush 由一个模板参数 (Class) 参数化,但您的专业化由两个模板参数 (TypeValue) 参数化。在通用模板中,Type 不是参数,因为它是从 Class.

推导出来的

一个有效但不令人满意的解决方案是:

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