我将variadic模板解压缩到模板别名时遇到了问题.
以下代码适用于Clang 3.4和GCC 4.8,但在GCC 4.9中失败:
template <typename T, typename...>
using front_type = T;
template <typename... Ts>
struct foo
{
using front = front_type<Ts...>;
};
Run Code Online (Sandbox Code Playgroud)
GCC 4.9抱怨:
test.cc:7:37: error: pack expansion argument for non-pack parameter 'T' of alias template 'template<class T, class ...> using front_type = T'
using front = front_type<Ts...>;
^
test.cc:1:15: note: declared here
template <typename T, typename...>
^
Run Code Online (Sandbox Code Playgroud)
存在一个提交的GCC错误(#59498),但这应该失败吗?以下是C++核心语言#1430的一些上下文,"将扩展打包到固定别名模板参数列表":
最初,包扩展无法扩展到固定长度的模板参数列表,但在N2555中已更改.这适用于大多数模板,但会导致别名模板出现问题.
在大多数情况下,别名模板是透明的; 当它在模板中使用时,我们可以在依赖模板参数中替换.但是,如果template-id对非可变参数使用包扩展,则这不起作用.例如:
Run Code Online (Sandbox Code Playgroud)template<class T, class U, class V> struct S {}; template<class …
考虑一个基于可变参数模板的别名,它在扩展表达式中使用它的第一个元素:
template<typename T, typename... Ts>
using AllSame = std::conjunction<std::is_same<T, Ts>...>;
Run Code Online (Sandbox Code Playgroud)
如果我们通过单独传递第一个元素来使用此别名,则代码编译良好:
template<typename T, typename... Ts>
using X = AllSame<T, Ts...>;
Run Code Online (Sandbox Code Playgroud)
但简单地传递整个包并不能编译:
template<typename... Ts>
using X = AllSame<Ts...>;
Run Code Online (Sandbox Code Playgroud)
这是编译错误:
error: pack expansion argument for non-pack parameter 'T' of alias template 'template<class T, class ... Ts> using AllSame = typename std::enable_if<std::is_same<bool_pack<true, std::is_same<T, Ts>::value ...>, bool_pack<std::is_same<T, Ts>::value ..., true> >::value>::type'
Run Code Online (Sandbox Code Playgroud)
为什么调用站点要单独传入第一个参数,而不是直接传入整个包?