C++ 将别名模板匹配为模板参数

C++ 将别名模板匹配为模板参数,c++,c++11,templates,language-lawyer,C++,C++11,Templates,Language Lawyer,考虑一下: #包括 模板 结构是:std::false类型{}的{u专门化}; 模板 结构是:std::true类型{}的{u专门化}; 模板 结构测试{}; //(1)好的 static_assert(是::value,“1”的_专门化_); 模板 使用别名=测试; //(2)失败 静态断言(是::value,“2”的专用化); int main() { } 为什么(2),即使用别名模板的静态断言,会失败 (2)中的模板参数推导过程与(1)中的模板参数推导过程有何不同 我认为没有模板参数列表

考虑一下:

#包括
模板
结构是:std::false类型{}的{u专门化};
模板
结构是:std::true类型{}的{u专门化};
模板
结构测试{};
//(1)好的
static_assert(是::value,“1”的_专门化_);
模板
使用别名=测试;
//(2)失败
静态断言(是::value,“2”的专用化);
int main()
{
}
为什么(2),即使用别名模板的
静态断言
,会失败


(2)中的模板参数推导过程与(1)中的模板参数推导过程有何不同

我认为没有模板参数列表的别名模板的名称与关联类型的名称不相等。因为标准只规定了一种情况:

14.5.7别名模板[临时别名]

  • 当模板id引用别名模板的专门化时,它相当于关联的类型 通过将其模板参数替换为别名的类型id中的模板参数而获得 模板。[注意:别名模板名称永远不会推导出来。-结束注意]
  • 这是:

    static_assert(是::value,“2”的特化);
    
    我认为没有模板参数列表的别名模板的名称与关联类型的名称不相等。因为标准只规定了一种情况:

    14.5.7别名模板[临时别名]

  • 当模板id引用别名模板的专门化时,它相当于关联的类型 通过将其模板参数替换为别名的类型id中的模板参数而获得 模板。[注意:别名模板名称永远不会推导出来。-结束注意]
  • 这是:

    static_assert(是::value,“2”的特化);
    
    这是一个。问题是:
    alias
    test
    是否等效?[temp.type]中曾经有一个例子,表明
    y
    z
    在这里具有相同的类型:

    这是。问题是:
    alias
    test
    是否等效?[temp.type]中曾经有一个例子,表明
    y
    z
    在这里具有相同的类型:


    那么,为什么如果我们删除
    test
    的第二个模板参数
    U
    ,那么一切都会编译得很好呢?是因为“别名模板名永远不会推导出来”。部分专门化是通过尝试推导专门化的参数来选择的。当编译器试图在专业化中推导<代码> t>代码>时,不考虑代码>别名>代码>,这实际上是175.7;请使用永久名称,在本例中为[临时别名]。(这样做的好处是可以链接到:)那么,为什么如果我们删除
    test
    的第二个模板参数
    U
    ,那么一切都可以很好地编译呢?是因为“别名模板名永远不会推导出来”。部分专门化是通过尝试推导专门化的参数来选择的。当编译器试图在专业化中推导<代码> t>代码>时,不考虑代码>别名>代码>,这实际上是175.7;请使用永久名称,在本例中为[临时别名]。有趣的是,如果我们更改
    test
    以获得一个模板参数,那么(2)仍然不会使用任何叮当声和GCC<4.9编译。这意味着GCC>=4.9已经实现了#1286。@IgorR。嗯,1286不是被采用的。有趣的是,如果我们改变
    test
    来获得一个模板参数,那么(2)仍然不会编译任何叮当声和GCC<4.9。这意味着GCC>=4.9已经实现了#1286。@IgorR。嗯,1286不是被采用的。因此,这可以说是不正确的。
    #include <type_traits>
    
    template<template<class...> class T, class... U>
    struct is_specialization_of : std::false_type{};
    
    template<template<class...> class T, class... U>
    struct is_specialization_of<T, T<U...>> : std::true_type{};
    
    template<class T, class U = int>
    struct test{};
    
    // (1) ok
    static_assert(is_specialization_of<test, test<int>>::value, "1");
    
    template<class T>
    using alias = test<T>;
    
    // (2) fails
    static_assert(is_specialization_of<alias, alias<int>>::value, "2");
    
    int main()
    {
    }
    
    static_assert(is_specialization_of<test, alias<int>>::value, "2");
    
    template<template<class> class TT> struct X { };
    template<class> struct Y { };
    template<class T> using Z = Y<T>;
    X<Y> y;
    X<Z> z;
    
    template<typename T, U = T> struct A;
    
    // ...
    
    template<typename V>   
      using D = A<V>;      // not equivalent to A:
                           // different number of parameters