别名模板,部分特化和无效参数类型void

时间:2016-03-08 22:43:15

标签: c++ templates c++11 void template-aliases

请考虑以下代码:

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的行,它没有编译,而是我得到了错误:

  

使用Alias = S代替&#39;模板[使用Args = {void}]&#39;

     

[...]

     

错误:参数类型无效&#39;无效&#39;

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

1 个答案:

答案 0 :(得分:5)

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

  

非依赖类型void的单个未命名参数组成的参数列表等同于空参数列表。除了这种特殊情况,参数不应具有 cv void类型。

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

  

[注意:类型扣除可能因以下原因而失败:
   - [...]
   - 尝试创建一个函数类型,其中参数的类型为void,或者返回   type是函数类型或数组类型    - [...]
   -end note]

请注意S<void(void)>编译,因为void(void)不依赖,并且等同于void(),因此永远不会推断Ret(Args...)在参数中有void列表 - 它是Args...空的推断。

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