bol*_*lov 40 c++ language-lawyer variadic-templates c++11 template-aliases
似乎只能在别名模板的pack参数的位置扩展pack参数.对于类或函数模板,情况并非如此:
template <class T, class... Args> struct x { using type = T; };
template <class T, class... Args> using x_t = typename x<T, Args...>::type;
template <class... Args> using x_fix_t = typename x<Args...>::type;
template <class... Args> auto f(Args...) -> void {
typename x<Args...>::type v1; // OK
x_t<Args...> v2; // Error
x_fix_t<Args...> v3; // OK
}
Run Code Online (Sandbox Code Playgroud)
更简单的情况:
template <class T, class U> using y_t = T;
template <class... Args> auto f(Args...) -> void {
y_t<Args...> v4; // Error
}
Run Code Online (Sandbox Code Playgroud)
上面的代码生成错误(即使f
从未实例化)与both c++11
和c++14
in g++ 4.9
,g++ 5.1
和clang 3.5
.
为什么不允许这样做,一般规则是什么?我认为没有理由限制这一点.这似乎是一个非常奇怪的禁令.
至于为什么不像x_fix_t
第一个变体那样写作,更明确的是x_t
有一个强制性的第一个参数.(例如,这是f()
不允许的原因).但这并不重要,修复很容易.问题仍然存在:为什么?
gcc错误:
error: pack expansion argument for non-pack parameter ‘T’ of
alias template ‘template<class T, class ... Args> using x_t = typename x::type’
Run Code Online (Sandbox Code Playgroud)
铿锵声:
error: pack expansion used as argument for non-pack parameter of
alias template x_t<Args...> v2;
Run Code Online (Sandbox Code Playgroud)
小智 19
这在GCC 4.8中编译但在GCC 4.9中失败,这证明它与DR1430和错误报告#59498有关.Roy Chrihfield提出的解决方案与您完全相同:
Rewriting the code to use a struct succeeds:
template <typename T, typename ...>
struct alias { using type = T; };
template <typename ...T>
using variadic_alias = typename alias<T...>::type;
Run Code Online (Sandbox Code Playgroud)
此外,Jason Merrill详细阐述了它为什么会失败:
实际上,不,这是一个核心1430问题; 没有提到修改过程中别名模板的名称就没有办法破坏variadic_alias,它们应该是完全透明的.这仅适用于4.8,因为发布时禁用了检查.
错误报告中不再存在进一步的讨论,因此我们可以转向DR1430:
最初,包扩展无法扩展到固定长度的模板参数列表,但在N2555中已更改.这适用于大多数模板,但会导致别名模板出现问题.
在大多数情况下,别名模板是透明的; 当它在模板中使用时,我们可以在依赖模板参数中替换.但是,如果template-id对非可变参数使用包扩展,则这不起作用.例如:
Run Code Online (Sandbox Code Playgroud)template<class T, class U, class V> struct S {}; template<class T, class V> using A = S<T, int, V>; template<class... Ts> void foo(A<Ts...>);
没有办法用S来表达A,所以我们需要保持A直到我们有Ts代替,因此它需要在修改中处理.
目前,EDG和Clang拒绝这个测试用例,抱怨A.G ++的模板参数太少,但我认为这是一个错误.然而,在ABI名单上,John Spicer认为它应该被拒绝.
(另见问题1558.)
2012年10月会议记录:
CWG的共识是,禁止使用此用法,当依赖参数不能简单地直接替换为type-id时,禁止使用别名模板.
附加说明,2013年4月:
再举一个例子,考虑:
Run Code Online (Sandbox Code Playgroud)template<class... x> class list{}; template<class a, class... b> using tail=list<b...>; template <class...T> void f(tail<T...>); int main() { f<int,int>({}); }
处理此示例时存在实现差异.
换句话说,这是一个持续的问题,没有任何解决方案(AFAIC).
归档时间: |
|
查看次数: |
1812 次 |
最近记录: |