【发布时间】:2015-08-22 19:02:44
【问题描述】:
似乎只能扩展包参数来代替别名模板的包参数。这不适用于类或函数模板:
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
}
更简单的情况:
template <class T, class U> using y_t = T;
template <class... Args> auto f(Args...) -> void {
y_t<Args...> v4; // Error
}
上述代码在g++ 4.9、g++ 5.1 和clang 3.5 中的c++11 和c++14 都会产生错误(即使f 从未实例化)。
为什么不允许这样做?一般规则是什么?我认为没有理由限制这一点。这似乎是一个很奇怪的禁令。
至于为什么不用第一个变体写成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’
clang 错误:
error: pack expansion used as argument for non-pack parameter of
alias template x_t<Args...> v2;
【问题讨论】:
-
这里的信息是相关的,我认为:stackoverflow.com/q/24433658/4326278
-
另外,对于它的价值,MSVC 12 和 14 RC 编译这个没有诊断(除了未引用变量的正常警告) - 正如他们所说的“实现差异”。
-
在 g++ 4.8.2 中工作正常。
-
ICC 13 也接受该代码——有没有标准的人可以指出说不?否则,这是一个很好的发现——回归不是一个,而是 两个 不同的实现!
标签: c++ c++11 language-lawyer variadic-templates template-aliases