我尝试理解14.5.5/8 of the C++11 standard的意义和含义(C++14中的同一性,我想,在C ++中17)
与专用非类型参数对应的模板参数的类型不应取决于特化的参数。
和往常一样,要了解g ++和clang ++之间的对应关系。
标准显示以下示例
template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error
并且g ++和clang ++都会出错。
到目前为止,非常好。
让我们复杂一点,添加一个类型的例子
template <typename, typename T, T>
struct foo { };
template <typename T>
struct foo<T, int, 1> { }; // compile
template <typename T>
struct foo<T, T, 1> { }; // error
g ++和clang ++都编译第一个部分特化(1
,int
的类型,不是特化的参数),并给第二个({{{{{ 1}}是1
,是专业化的参数)
到目前为止,非常好。
让我们介绍一个模板结构T
,其内部类型不依赖于模板参数
bar
以及以下计划
template <typename>
struct bar
{ using type = int; };
它是在没有错误的情况下通过g ++编译的(在wandbox中使用4.9.3,5.5.0,7.2.0和头部8.0.0;使用c ++ 11,c ++ 14以及可用时,c ++ 17 )但clang ++(3.9.1,4.0.1,5.0.0,head 6.0.0; c ++ 11,c ++ 14,c ++ 17)给出以下错误
template <typename>
struct bar { using type = int; };
template <typename, typename T, T>
struct foo { };
template <typename T>
struct foo<T, typename bar<T>::type, 1> { };
int main ()
{ }
像往常一样:谁是对的?
clang ++,考虑prog.cc:11:38: error: non-type template argument specializes a template parameter with dependent type 'T'
struct foo<T, typename bar<T>::type, 1> { };
^
prog.cc:7:34: note: template parameter is declared here
template <typename, typename T, T>
~^
依赖于1
(当T
被修复为typename bar<T>::type
时)或g ++不能减轻这种依赖性?
为了完整性,我不得不说如下更改int
bar
所以使template <typename T>
struct bar { using type = T; };
依赖于bar<T>::type
,没有任何改变:g ++编译没有错误,而clang ++给出了同样的错误。
答案 0 :(得分:2)
从编译器的角度来看它。
template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error
对于专业化,编译器不知道T
是否确实具有值1
,因此专业化无效。
有关
template <typename T>
struct foo<T, typename bar<T>::type, 1> { };
谁在说type
总是int
?您可能认为这很明显,但我可以针对一个特定的bar
引入T
的特化,以便type
为std::string
:
template<>
struct bar<const volatile int> { using type = std::string };
基本上,您的声明“当typename bar<T>::type
被修复为int
”时出错了,它不是固定的。
现在怎样?这里的标准与第一个例子说的相同,专业化是不正确的,因为正如你的引用正确陈述的那样,非类型参数的类型取决于专业化的另一个(模板化)类型,即{{1这是未知的。在这方面,铿锵是对的,而gcc是错的。