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.