41

我使用带有标志 c++0x 的 g++ 4.6.3(当前是 ubuntu 12.04 的默认包),我偶然发现了这个:

template <typename T>
inline T getValue(AnObject&)
{
    static_assert(false , "this function has to be implemented for desired type");
}

编译错误:

static_assertion failed "this function has to be implemented for the desired type"

即使我还没有在任何地方调用这个函数

它是一个 g++ 错误吗?仅当在代码中的某处调用此函数时才应实例化此函数。

4

4 回答 4

63

标准在 [temp.res]/8 中说

对于可以生成有效特化的模板定义,不应发出诊断。如果无法为模板定义生成有效的特化,并且该模板未实例化,则模板定义格式错误,无需诊断。... [注:如果模板被实例化,错误将根据本标准中的其他规则进行诊断。准确诊断这些错误的时间是实施质量问题。——尾注]

无法实例化将编译的函数模板,因此模板定义格式错误,因此即使未实例化,编译器也允许(但不是必需)拒绝它。

你可以让它像这样工作:

template<typename T>
struct foobar : std::false_type
{ };

template <typename T>
inline T getValue(AnObject&)
{
    static_assert( foobar<T>::value , "this function has to be implemented for desired type");
}

现在编译器不能立即拒绝函数模板,因为在它被实例化之前,它不知道是否会有foobar那个 has的特化value == true。当实例化时,相关的特化foobar<T>将被实例化,静态断言仍然会失败,如所愿。

于 2013-02-01T00:11:09.520 回答
33

这是因为条件不以任何方式依赖于模板参数。因此,编译器甚至可以在实例化该模板之前对其进行评估,并在评估产生时产生相关的编译错误消息false

换句话说,这不是一个错误。虽然很多事情只能在模板实例化后才能检查,但编译器甚至可以在之前执行其他有效性检查。例如,这就是 C++ 具有两阶段名称查找的原因。编译器只是试图帮助您找到 100% 可能发生的错误。

于 2013-01-31T23:56:27.290 回答
5

这确实是一个注释,但需要一个代码示例。

神圣标准的措辞static_assert并不限制其对实例化代码的影响。

然而,代码

template <typename T>
inline T getValue(int&)
{
    typedef char blah[-1];  // Common C++03 static assert, no special semantics.
}

int main()
{}

也无法使用 MinGW g++ 4.7.2 编译,这突出了这个问题。

认为答案是 g++ 是对的,而不会为此产生编译错误的 Visual C++ 11.0 是错误的,但我很难根据神圣标准的经文提供相关分析。

编译器差异的一个实际后果是目前您不能依赖该行为。

于 2013-02-01T00:09:37.243 回答
0

只是-fdelayed-template-parsing

于 2020-12-04T15:03:18.287 回答