static_assert 在未初始化的模板中 class 具有有效的专业化
static_assert in not initialized template class with valid specialization
我的问题是,下面的代码是否有效:
template<int i> class Class
{
static_assert(sizeof(i) == 0, "Class instantiated with i != 1");
};
template<> class Class<1> {};
此代码段使用 g++
编译。但是 clang++
被 static_assert
:
困住了
error: static_assert failed "Class instantiated with non-int type"
使用类型而不是 int
类型的模板,例如
template<typename T> class Class
{
static_assert(sizeof(T) == 0, "Class instantiated with non-int type");
};
template<> class Class<int> {};
被两个编译器接受。完全相同的模式适用于函数模板。
我找到了 open-std.org::Non-dependent static_assert-declarations,但这似乎不适用,因为我的 static_assert
依赖于模板参数。
您可以在 godbolt.org
上查看所描述的行为
编辑:正如 Johan Lundberg 在评论中指出的那样,我的问题是错误的。实际上 sizeof(i)
不依赖于模板参数。 R.Sahu 也是完全正确的:断言 i != 1
会更有意义。为此,两个编译器再次接受代码。
然而,上面的例子仍然可以用g++
编译。由于 open-std.org::Non-dependent static_assert-declarations 适用于那种情况(我再次为这方面的错误问题道歉): Is g++
actually wrong in compiling the code without error?
首先,如果你想断言模板是用错误的类型实例化的,你必须在 static_assert:
中显式
#include <type_traits>
template<typename T> class Class
{
static_assert(std::is_same<T, int>::value, "Class instantiated with non-int type");
};
其次,下面这行可能不是你想的那样:
template<> class Class<int> {};
您实际上在这里做的是创建一个全新的专业化,它与默认模板专业化没有任何关系Class<T>
。
删除 int
的特化并实例化默认特化的非整数 class 会在两个编译器中产生错误,因为它应该:
int main()
{
Class<int> ci;
Class<float> cf;
}
示例错误:
<source>: In instantiation of 'class Class<float>':
<source>:14:18: required from here
<source>:5:5: error: static assertion failed: Class instantiated with non-int type
static_assert(std::is_same<T, int>::value, "Class instantiated with non-int type");
^~~~~~~~~~~~~
clang++拒绝你的代码是对的,但是g++没有捕捉到错误也不是错;这是“无需诊断”的情况。
标准将模板中的表达式严格定义为“依赖于类型”and/or“依赖于值”。给定 template<int i>
,i
依赖于值但不依赖于类型。
[14.6.2.2/4]: Expressions of the following forms are never type-dependent (because the type of the expression cannot be dependent):
- ...
sizeof
unary-expression
- ...
[14.6.2.3/2]: Expressions of the following form are value-dependent if the unary-expression or expression is type-dependent or the type-id is dependent:
sizeof
unary-expression
- ...
所以sizeof(i)
不依赖。
最后,14.6/8 说:
If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed; no diagnostic is required.
我的问题是,下面的代码是否有效:
template<int i> class Class
{
static_assert(sizeof(i) == 0, "Class instantiated with i != 1");
};
template<> class Class<1> {};
此代码段使用 g++
编译。但是 clang++
被 static_assert
:
error: static_assert failed "Class instantiated with non-int type"
使用类型而不是 int
类型的模板,例如
template<typename T> class Class
{
static_assert(sizeof(T) == 0, "Class instantiated with non-int type");
};
template<> class Class<int> {};
被两个编译器接受。完全相同的模式适用于函数模板。
我找到了 open-std.org::Non-dependent static_assert-declarations,但这似乎不适用,因为我的 static_assert
依赖于模板参数。
您可以在 godbolt.org
上查看所描述的行为编辑:正如 Johan Lundberg 在评论中指出的那样,我的问题是错误的。实际上 sizeof(i)
不依赖于模板参数。 R.Sahu 也是完全正确的:断言 i != 1
会更有意义。为此,两个编译器再次接受代码。
然而,上面的例子仍然可以用g++
编译。由于 open-std.org::Non-dependent static_assert-declarations 适用于那种情况(我再次为这方面的错误问题道歉): Is g++
actually wrong in compiling the code without error?
首先,如果你想断言模板是用错误的类型实例化的,你必须在 static_assert:
中显式#include <type_traits>
template<typename T> class Class
{
static_assert(std::is_same<T, int>::value, "Class instantiated with non-int type");
};
其次,下面这行可能不是你想的那样:
template<> class Class<int> {};
您实际上在这里做的是创建一个全新的专业化,它与默认模板专业化没有任何关系Class<T>
。
删除 int
的特化并实例化默认特化的非整数 class 会在两个编译器中产生错误,因为它应该:
int main()
{
Class<int> ci;
Class<float> cf;
}
示例错误:
<source>: In instantiation of 'class Class<float>':
<source>:14:18: required from here
<source>:5:5: error: static assertion failed: Class instantiated with non-int type
static_assert(std::is_same<T, int>::value, "Class instantiated with non-int type");
^~~~~~~~~~~~~
clang++拒绝你的代码是对的,但是g++没有捕捉到错误也不是错;这是“无需诊断”的情况。
标准将模板中的表达式严格定义为“依赖于类型”and/or“依赖于值”。给定 template<int i>
,i
依赖于值但不依赖于类型。
[14.6.2.2/4]: Expressions of the following forms are never type-dependent (because the type of the expression cannot be dependent):
- ...
sizeof
unary-expression- ...
[14.6.2.3/2]: Expressions of the following form are value-dependent if the unary-expression or expression is type-dependent or the type-id is dependent:
sizeof
unary-expression- ...
所以sizeof(i)
不依赖。
最后,14.6/8 说:
If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed; no diagnostic is required.