【问题标题】:Are multiple non-type template parameter packs allowed?是否允许多个非类型模板参数包?
【发布时间】:2015-07-29 09:54:41
【问题描述】:

[temp.param] p11 说(在 N4527 中):

(...) 函数模板的模板形参包后面不应有另一个模板形参,除非该模板形参可以从函数模板的形参类型列表中推导出来或具有默认实参

非类型模板参数包的上下文中,不能有默认参数,
那么究竟需要为包推断什么(也只是类型或值)?

即我想知道标准(C++11、14 或 1z)是否允许这样做:

template<typename T, T... A, T... B>
void foo(T) {}

第一个包的值可以明确指定,但第二个包是“无法访问”的,如果我没记错的话,它总是空的。

clang++-3.6 和 g++-5.2 似乎接受这些空的无法访问的包(甚至是非类型包),但 VC++ 14.0 拒绝它们并出现错误:

错误C3547:模板参数'B'不能使用,因为它遵循模板参数包,不能从'foo'的函数参数推导出来

【问题讨论】:

  • 这些值必须是可推断的。令人惊讶的是,MSVC 是对的。看起来两者都没有实现此检查,因为两者都没有诊断出template&lt;class... T, class... U&gt; void f() { },标准明确地将其标记为“错误”。
  • 我希望非类型参数包存在漏洞:(
  • 呃,标准需要修复:S 没有理由禁止这样做。
  • @R.MartinhoFernandes 模板参数的意义何在,您永远无法为其提供参数?
  • @T.C.如果这是基本原理,那么“或具有默认参数”也不会有例外。 (我一直使用这些类型的包;它们是 SFINAE 选择重载 IMO 的最佳方式)

标签: c++ templates c++11 language-lawyer


【解决方案1】:

不,标准不允许。来自 [temp.param]:

不应遵循函数模板的模板参数包 由另一个模板参数,除非该模板参数可以从 parameter-type-list 中推导出来 函数模板或具有默认参数 (14.8.2)。 [例子:

template<class T1 = int, class T2> class B;    // error

// U can be neither deduced from the parameter-type-list nor specified
template<class... T, class... U> void f() { }  // error
template<class... T, class U> void g() { }     // error

——结束示例]

在您的情况下,...B 无法推断(因为没有什么可推断的)并且它没有默认参数。

那么究竟需要为包推导出什么(只是类型或值)?

例如,如果您的 foo 是:

template <size_t... A, size_t... B>
void foo(std::index_sequence<B...> );

...A后面跟着...B,但是...B可以推导出来,所以是允许的。同样:

template <typename T, T... A, T B = 0>
void foo();

很好,因为B 有一个默认参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-18
    • 2016-12-06
    • 1970-01-01
    • 2013-12-08
    相关资源
    最近更新 更多