【问题标题】:Alias template, partial specialization and the invalid parameter type void别名模板、部分特化和无效参数类型 void
【发布时间】:2016-06-23 02:45:09
【问题描述】:

考虑以下代码:

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&lt;void(int)&gt;

现在,考虑以下更改:

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

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

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

[...]

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    [注:类型扣减可能会失败,原因如下:
    — [...]
    — 试图创建一个函数类型,其中参数的类型为 void,或者返回 type 是函数类型或数组类型。
    — [...]
    —结束注 ]

    请注意,S&lt;void(void)&gt; 可以编译,因为void(void) 是非依赖的,并且等价于void(),因此Ret(Args...) 永远不会被推导出为在参数列表中包含void - 它是用Args... 为空推导出来的。


    至少有一个简单的解决方法,你可以写Alias&lt;&gt;

    【讨论】:

    • 解决方法很明显,但它不应该因为同样的原因编译两行都失败吗?此外,S&lt;void(void)&gt; 导致推导尝试(嗯,成功)创建一个函数类型,其中参数的类型为void。我错了吗?
    • @skypjack 刚刚找到我要找的部分。 void 必须是非依赖的。
    • 感谢您的参考。无论如何,Args 中的Args 不也是应该遭受同样问题的依赖类型吗?
    • @skypjack 我认为你很好,因为你明确地传递了void(void)。无论如何,都不是 100% 确定
    • 你知道,我正在为此创建一个新问题,所以开始四处寻找参考的正确部分! :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    相关资源
    最近更新 更多