static_assert在未初始化的模板类中,具有有效的特化

时间:2017-04-07 20:56:32

标签: c++ templates static-assert

我的问题是,以下代码是否有效:

template<int i> class Class
{
    static_assert(sizeof(i) == 0, "Class instantiated with i != 1");
};

template<> class Class<1> {};

此代码段与g++一起编译。但是clang++static_asserterror: 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> {}; 的模板

static_assert
两个编译器都接受

。完全相同的模式适用于函数模板。

我找到open-std.org::Non-dependent static_assert-declarations,但这似乎不适用,因为我的sizeof(i)依赖于模板参数。

您可以在godbolt.org

上查看所描述的行为

编辑:正如Johan Lundberg在评论中指出我的问题是错误的。实际上i != 1不依赖于模板参数。 R.Sahu也是完全正确的:断言g++会更有意义。为此,两个编译器都接受了代码。

但是,上面的示例仍然使用g++进行编译。由于open-std.org::Non-dependent static_assert-declarations适用于该情况(我在这方面再次为错误的问题道歉):{% for tag in product.tags %} {% if tag contains 'top' %} {% assign settings.home_featured_products == 'Home' %} {% elsif tag contains 'bottom' %} {% assign settings.home_featured_products == 'Frontpage' %} {% endif %} {% endfor %} 在编译代码时是否真的错误而没有错误?

2 个答案:

答案 0 :(得分:1)

clang ++拒绝你的代码是正确的,但g ++没有错误地捕获错误;这是一个&#34;无需诊断&#34;情况。

标准严格地将模板中的表达定义为&#34;类型相关&#34;和/或&#34;价值相关&#34;。给定template<int i>i取决于值,但不依赖于类型。

  

[14.6.2.2/4]:以下形式的表达式从不依赖于类型(因为表达式的类型不能依赖):

     
      
  • ...
  •   
  • sizeof 一元表达
  •   
  • ...
  •   
     

[14.6.2.3/2]:如果一元表达式表达式依赖于类型或,则以下表单的表达式是值依赖的type-id 依赖:

     
      
  • sizeof 一元表达
  •   
  • ...
  •   

所以sizeof(i)不依赖。

最后,14.6 / 8说:

  

如果由于不依赖于模板参数的构造而在其定义之后立即对模板进行假设实例化,那么该程序就会形成错误;无需诊断。

答案 1 :(得分:0)

首先,如果要断言模板已使用错误的类型进行实例化,则必须在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的特化并且实例化默认特化的非int类会在两个编译器中产生错误:

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");
     ^~~~~~~~~~~~~