15

我遇到了将可变参数模板解压缩为模板别名的问题。

以下代码适用于 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...>;
};

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...>
               ^

存在一个归档的 GCC 错误(#59498),但这应该失败吗?以下是C++ 核心语言问题 #1430 的一些上下文,“将扩展打包到固定别名模板参数列表中”

最初,包扩展无法扩展为固定长度的模板参数列表,但在 N2555 中进行了更改。这适用于大多数模板,但会导致别名模板出现问题。

在大多数情况下,别名模板是透明的;当它在模板中使用时,我们可以替换依赖的模板参数。但是,如果模板 ID 对非可变参数使用包扩展,这将不起作用。例如:

  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...>);

没有办法用 来表示A<Ts...>S所以我们需要坚持A直到我们有Ts 可以替换,因此需要在 mangling 中处理。

目前,EDG 和 Clang 拒绝了这个测试用例,抱怨 A 的模板参数太少。G++ 也是如此,但我认为这是一个错误。然而,在 ABI 名单上,John Spicer 认为它应该被拒绝。

4

1 回答 1

12

在 gcc4.9 bugzilla 中报告:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59498

重现的最少代码

template <typename T, typename ...>
using alias = T;

template <typename ...T>
using variadic_alias = alias<T...>;

using Fail = variadic_alias<int>;

int main() { }

From the explanation from gcc folks - it is not so obvious this is a real bug. This is still discussion held in gcc bugzilla and in DR 1430 (http://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1430) - summary in now in the question above.

于 2014-06-26T15:07:17.027 回答