当type参数为void时,无法实例化函数模板

时间:2012-09-08 16:30:39

标签: c++ templates c++11

我们知道以下代码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

毕竟,这就是我要求的。

我正在寻找权威的答案。

2 个答案:

答案 0 :(得分:5)

法律论证是void是一个无法完成的不完整类型,因此永远不能用作顶级类型。与void a;比较。这有点令人困惑,因为参数列表中的void不是类型,而是指示无参数的约定。

答案 1 :(得分:3)

C兼容性语法攻击

以下内容:

void f() {}
void g(void) {}

f();
g();

编译只是因为出于C兼容性原因而保留了有问题的C ++语法符号,即g中的void

void g(void) {}

在这里用来说“没有参数”,而不是,可以预期“void类型的一个参数”(这没有意义)。

在C ++中,我们有时需要包含C头,因此如果不支持此注释,则会出现问题。但这并不意味着你必须在你的C ++代码中使用它。

C ++模板

宣布:

template<typename T>
void g(T) {}

您正在声明g类型上的函数T,该函数有一个类型为T的未命名参数。

因此,当Tvoid时,您仍在处理函数g,该函数有一个类型为void的未命名参数。这毫无意义。这意味着编译器会抱怨。

解?

真的?

根本不要使用g(void)表示法。这就像C ++中的typedefing结构一样。它没用,只会混淆代码。

解决方案2?

现在,如果你真的有以下代码:

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>() */ }