10

考虑以下代码:

template<typename F>
struct S;

template<typename Ret, typename... Args>
struct S<Ret(Args...)> { };

template<typename... Args>
using Alias = S<void(Args...)>;

int main() {
    S<void(int)> s;
    Alias<int> alias;
}

它工作正常,正如预期的那样,涉及的行S和涉及的行都Alias在引擎盖下定义了相同的类型S<void(int)>

现在,考虑以下更改:

int main() {
    S<void(void)> s;  // this line compiles
    Alias<void> alias;  // this line does not
}

我希望它能够编译,原因与上述类似。
不用说,由于涉及 的行,它没有编译Alias,而是我得到了错误:

代替“使用别名 = S [with Args = {void}] 的模板”

[...]

错误:无效的参数类型'void'

问题很简单:我在这里错过了什么?

4

1 回答 1

5

来自 [dcl.fct],强调我的:

由单个非依赖类型的未命名参数组成的参数列表void等效于空参数列表。除此特殊情况外,参数不得具有cv void类型。

在这种情况下,Args...是一个依赖类型包,所以void不允许出现。在 [temp.deduct] 的注释中重复了这个想法:

[注意:类型推导可能因以下原因而失败:
— [...]
— 尝试创建一个函数类型,其中参数的类型为void,或者返回类型为函数类型或数组类型。
— [...] —
尾注]

请注意,S<void(void)>compiles sincevoid(void)是非依赖的并且等价于void(), 所以Ret(Args...)永远不会被推断为void在参数列表中 - 它被推断为Args...空。


至少有一个简单的解决方法,您可以编写Alias<>.

于 2016-03-08T23:01:07.603 回答