3

我们知道以下代码编译得很好

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>() 给出错误

错误:没有匹配的函数调用“g()”

为什么不能将其实例void化为类型参数?为什么函数模板没有实例化为:

void g(void) {}  //to be instantiated from the function template

毕竟,这是我要求的。

我正在寻找一个权威的答案。

4

2 回答 2

5

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

于 2012-09-08T16:34:48.500 回答
3

C 兼容性语法破解

以下:

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

f();
g();

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

void g(void) {}

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

在 C++ 中,我们有时需要包含 C 头文件,因此如果不支持这种表示法,就会出现问题。但这并不意味着您必须在 C++ 代码中使用它。

C++ 模板

当您声明:

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

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

所以,当Tvoid,你仍在处理一个函数g,它有一个类型为 的未命名参数void。这没有任何意义。这意味着编译器会抱怨。

解决方案?

严重地?

根本不要使用g(void)符号。这就像 C++ 中的 typedef-ing 结构。它没有用,只会混淆代码。

解决方案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 情况:

// 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>() */ }
于 2012-09-08T17:07:39.723 回答