我们知道以下代码compiles fine:
void f() {}
void g(void) {}
f();
g();
但为什么不是以下内容:
template<typename T>
void f() {}
template<typename T>
void g(T) {}
f<void>(); //ok
g<void>(); //error
为什么行g<void>()
gives error?
错误:没有匹配函数来调用'g()'
为什么不能用void
作为类型参数进行实例化?为什么函数模板没有实例化为:
void g(void) {} //to be instantiated from the function template
毕竟,这就是我要求的。
我正在寻找权威的答案。
答案 0 :(得分:5)
法律论证是void
是一个无法完成的不完整类型,因此永远不能用作顶级类型。与void a;
比较。这有点令人困惑,因为参数列表中的void
不是类型,而是指示无参数的约定。
答案 1 :(得分:3)
以下内容:
void f() {}
void g(void) {}
f();
g();
编译只是因为出于C兼容性原因而保留了有问题的C ++语法符号,即g中的void
:
void g(void) {}
在这里用来说“没有参数”,而不是,可以预期“void
类型的一个参数”(这没有意义)。
在C ++中,我们有时需要包含C头,因此如果不支持此注释,则会出现问题。但这并不意味着你必须在你的C ++代码中使用它。
宣布:
template<typename T>
void g(T) {}
您正在声明g
类型上的函数T
,该函数有一个类型为T的未命名参数。
因此,当T
为void
时,您仍在处理函数g
,该函数有一个类型为void
的未命名参数。这毫无意义。这意味着编译器会抱怨。
真的?
根本不要使用g(void)
表示法。这就像C ++中的typedefing结构一样。它没用,只会混淆代码。
现在,如果你真的有以下代码:
template<typename T>
void g(T) {}
如果你想提供g()
实现,你应该提供一个重载:
// Original template
template<typename T>
void g(T) { /* implementation for the generic case */ }
// Code to handle g()
void g() { /* implementation for the specific "void" case */ }
如果你想提供g<void>()
实现,你应该提供一个模板化的重载,通过专门化来处理void case:
// Original template
template<typename T>
void g(T) { /* implementation for the generic case for g(T) */ }
// Code to handle g<void>()
template<typename T>
void g() { /* implementation for the generic case for g() */ }
template<>
void g<void>() { /* implementation for the generic case for g<void>() */ }