C++ 11 static_assert和模板实例化

use*_*370 48 c++ c++11

在C++ 11中,模板中static_assert的操作是否应该取决于该模板是否已经实例化?例如,使用以下代码

template <int I>
void sa() { static_assert(0,"Hello."); }

int main(int argc, char *argv[]) { return 0; }
Run Code Online (Sandbox Code Playgroud)

GCC 4.5.0将无法断言,并生成"Hello".信息.另一方面,Digital Mars Compiler版本8.42n没有给出任何消息.

Joh*_*itb 50

GCC是正确的,其他编译器也是正确的.请参阅规格中的14.6p8

如果无法为模板定义生成有效的专业化,并且未实例化该模板,则模板定义不正确,无需诊断.

因此,编译器可以自由拒绝以下内容

template<typename T>
void f() {
  static_assert(0, "may trigger immediately!");
  static_assert(sizeof(T) == 0, "may trigger immediately!");
}
Run Code Online (Sandbox Code Playgroud)

如果你想要安全,你必须安排它,以便编译器在实例化之前无法知道布尔表达式是真还是假.例如,通过获取的价值getvalue<T>::value,有getvalue是一个类模板(一个可以专注,所以编译器不可能知道布尔值的话).

  • 也许`std :: is_same_v <T,T>`出现时最方便. (4认同)

Pup*_*ppy 8

我相信编译器完全有权扩展任何不依赖于模板参数的静态断言而不需要实例化 - 但我不认为这是必需的.还要记住,不同的标准草案可能会对何时发生这种情况有不同的规定.


Ant*_*ams 6

C++0x 草案 ( N3242 ) 在 14.6p8 中说:

\n\n
\n

“如果无法为模板定义生成\n 有效的专业化,\n 并且该模板未实例化,\n 模板定义\n 格式不正确,\n 无诊断必需的。”

\n
\n\n

同样的词语也出现在C++03标准中。

\n\n

对于问题中的示例,无法为此模板进行有效的实例化,因此引用的措辞适用。

\n\n

由于不需要诊断,因此如果模板未实例化,则编译器可以编译程序。当然,如果实例化了该程序,则该程序格式错误,需要进行诊断。

\n

  • **不需要**任何诊断,但程序仍然格式错误,因此编译器**可能**拒绝编译它。gcc 和 Digital Mars 都表现出一致的行为。 (8认同)

sta*_*lue 5

我使用了一个辅助函数来使 false 依赖于模板参数:

template<typename T> 
bool dependentFalse<T>()
{
    return false;
}

template<typename T>
Foo foo()
{
    static_assert(dependentFalse<T>(), "this template shouldn't be instantiated");
}
Run Code Online (Sandbox Code Playgroud)