在模板定义中使用空的尖括号

21

这是一道面试题:

这段代码是否会导致编译/链接错误?为什么会出现这种情况?
template <int T> void f();
template <> void f<0>() {}

void test() 
{
    f<1>();
}
请解释这个行为。非常感谢。

2
链接错误,您需要 template <int T> void f() { } - P0W
3个回答

24
template<> void f<0>() {}

如果你调用 f<0>(),这个函数模板的特化将被调用,它是针对参数0的。

这段代码是不正确的,它会导致链接错误,因为没有对f<1>进行特化,同时模板版本的函数也没有被定义


为什么在定义中跳过了<int T>语句?这可能吗? - Netherwire
@Netherwire 是的,因为它是特化,template<> 指向函数的完全特化。 - ForEveR
那我们应该包括 template <int T> void f() { } 来涵盖所有情况,对吧?还是只需要 template <> void f<1>() {} 来定义另一个特殊情况?我已经检查过了。 - Chan Kim

8

这段代码在语法上没有问题,可以编译通过,但在链接阶段会失败。

原因是声明了template <int T> void f();但未定义,而<0>特化已被定义,但对于你来说并没有什么影响,因为你没有实例化它。

实际上,就算<0>特化中存在语法错误,程序仍然可以编译通过!这是因为在模板中,只有当使用时才会被编译。(我不指望面试者在紧张的面试环境下能想到指出这一点。)


“<0> 特化可能包含语法错误,但程序仍然可以编译而不出错!” - 这是正确的,但只有在宽松的编译器下才能实现。其他编译器则不能这样做。 - ach
1
不,这是标准的一部分。 - Bathsheba
我认为即使这是标准的一部分,只包含语法错误的<0>专业化也可能会编译; 这不能保证。如果它包含额外的未匹配的}语法错误,则编译器可能会有问题确定函数定义应该结束的位置,导致它在下一行解析不正确。 - Variadicism

4

它将被编译,因为编译器可以看到通用模板的声明。也有一个完全专门化的模板0。但我们正在调用1的模板,这将尝试调用通用模板,但由于链接器找不到通用模板的任何定义,程序将显示链接器错误。

解决方法

template <int T> void f();
template <> void f<0>() {}
template <int T> void f() { }


void test() 
{
  f<1>();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接