静态断言(A::B::value==1,“”); #else//Expected=> 静态_断言(A::B::value==2,“”); #恩迪夫 CLAN不考虑代码>模板B < /代码>的部分专门化。GCC一直在考虑这一点。只有在声明A::B的部分专门化之前强制A实例化,clang才会有这种“意外”行为。如果我们声明专用主模板的部分专用化a::B,则clang具有预期的行为,c++,c++11,templates,language-lawyer,C++,C++11,Templates,Language Lawyer" /> 静态断言(A::B::value==1,“”); #else//Expected=> 静态_断言(A::B::value==2,“”); #恩迪夫 CLAN不考虑代码>模板B < /代码>的部分专门化。GCC一直在考虑这一点。只有在声明A::B的部分专门化之前强制A实例化,clang才会有这种“意外”行为。如果我们声明专用主模板的部分专用化a::B,则clang具有预期的行为,c++,c++11,templates,language-lawyer,C++,C++11,Templates,Language Lawyer" />

C++ 在实例化封闭类模板之后,我们可以声明模板类成员的部分专门化吗? 让我们考虑这个简单的例子: template<class T> struct A{ template<class V,class=void> struct B{ static const int value=1 ; }; }; #ifdef PRE_INSTANTIATION A<int> a; #endif #ifdef PARTIAL_SPECIALIZATION_OF_TEMPLATE_MEMBER template<class T> template<class V> struct A<T>::B<double,V>{ static const int value = 2; }; #else //PARTIAL_SPECIALIZATION_OF_SPECIALIZATION_MEMBER template<> template<class V> struct A<int>::B<double,V>{ static const int value = 2; }; #endif static_assert(A<int>::B<int>::value==1,""); #if __clang__ && PRE_INSTANTIATION && PARTIAL_SPECIALIZATION_OF_TEMPLATE_MEMBER //Unexpected => static_assert(A<int>::B<double>::value==1,""); #else //Expected => static_assert(A<int>::B<double>::value==2,""); #endif 模板 结构A{ 模板 结构B{ 静态常数int值=1; }; }; #ifdef预实例化 A A; #恩迪夫 #ifdef模板成员的部分专业化 模板 模板 结构A::B{ 静态常数int值=2; }; #else//PARTIAL\u SPECIALIZATION\u成员的部分\u SPECIALIZATION\u 模板 模板 结构A::B{ 静态常数int值=2; }; #恩迪夫 静态断言(A::B::value==1,“”); #如果模板成员的实例化和部分专业化 //意外=> 静态断言(A::B::value==1,“”); #else//Expected=> 静态_断言(A::B::value==2,“”); #恩迪夫 CLAN不考虑代码>模板B < /代码>的部分专门化。GCC一直在考虑这一点。只有在声明A::B的部分专门化之前强制A实例化,clang才会有这种“意外”行为。如果我们声明专用主模板的部分专用化a::B,则clang具有预期的行为

C++ 在实例化封闭类模板之后,我们可以声明模板类成员的部分专门化吗? 让我们考虑这个简单的例子: template<class T> struct A{ template<class V,class=void> struct B{ static const int value=1 ; }; }; #ifdef PRE_INSTANTIATION A<int> a; #endif #ifdef PARTIAL_SPECIALIZATION_OF_TEMPLATE_MEMBER template<class T> template<class V> struct A<T>::B<double,V>{ static const int value = 2; }; #else //PARTIAL_SPECIALIZATION_OF_SPECIALIZATION_MEMBER template<> template<class V> struct A<int>::B<double,V>{ static const int value = 2; }; #endif static_assert(A<int>::B<int>::value==1,""); #if __clang__ && PRE_INSTANTIATION && PARTIAL_SPECIALIZATION_OF_TEMPLATE_MEMBER //Unexpected => static_assert(A<int>::B<double>::value==1,""); #else //Expected => static_assert(A<int>::B<double>::value==2,""); #endif 模板 结构A{ 模板 结构B{ 静态常数int值=1; }; }; #ifdef预实例化 A A; #恩迪夫 #ifdef模板成员的部分专业化 模板 模板 结构A::B{ 静态常数int值=2; }; #else//PARTIAL\u SPECIALIZATION\u成员的部分\u SPECIALIZATION\u 模板 模板 结构A::B{ 静态常数int值=2; }; #恩迪夫 静态断言(A::B::value==1,“”); #如果模板成员的实例化和部分专业化 //意外=> 静态断言(A::B::value==1,“”); #else//Expected=> 静态_断言(A::B::value==2,“”); #恩迪夫 CLAN不考虑代码>模板B < /代码>的部分专门化。GCC一直在考虑这一点。只有在声明A::B的部分专门化之前强制A实例化,clang才会有这种“意外”行为。如果我们声明专用主模板的部分专用化a::B,则clang具有预期的行为,c++,c++11,templates,language-lawyer,C++,C++11,Templates,Language Lawyer,叮当声对吗?或者这里有没有未经诊断的UB 请注意,自c++11支持以来的所有clang版本都具有此行为,自c++11支持以来的所有gcc版本都具有“预期”行为 这个 根据建议中遵循的方向,gcc 行为可以标准化: 对于给定的实例化类 专门化,首选的主要成员模板,部分 可以显式声明专门化或完全专门化 目前的C++标准不规范,结构形式良好,但结果不明确。 这被报告为感觉像是格式不正确的NDR。@我刚刚在标准中找到的路人。但我仍然不确定,因为B是主模板的部分专用化,而不是主模板的专用化。@路人最后说

叮当声对吗?或者这里有没有未经诊断的UB


请注意,自c++11支持以来的所有clang版本都具有此行为,自c++11支持以来的所有gcc版本都具有“预期”行为

这个

根据建议中遵循的方向,gcc 行为可以标准化:

对于给定的实例化类 专门化,首选的主要成员模板,部分 可以显式声明专门化或完全专门化

目前的C++标准不规范,结构形式良好,但结果不明确。


这被报告为

感觉像是格式不正确的NDR。@我刚刚在标准中找到的路人。但我仍然不确定,因为B是主模板的部分专用化,而不是主模板的专用化。@路人最后说,这是对标准的一个欠规范,并且被报告为一个叮当作响的bug。