别名模板的包扩展 [英] Pack expansion for alias template

查看:101
本文介绍了别名模板的包扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎可以仅在别名模板的pack参数的位置上将pack参数扩展为.对于类或函数模板,情况并非如此:

It seems that a pack argument can be expanded only in the place of a pack parameter of an alias template. This is not true for a class or a function template:

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.9g++ 5.1clang 3.5中的c++11c++14都产生错误(即使从未实例化f).

The above code generates error (even if f is never instantiated) with both c++11 and c++14 in g++ 4.9, g++ 5.1 and clang 3.5.

为什么不允许这样做?一般规则是什么?我认为没有理由限制这一点.看来这是一个很奇怪的禁令.

Why is this not permitted and what is the general rule? I see no reason to restrict this. It seems a very strange prohibition.

至于为什么不使用第一个变体写为x_fix_t,则更清楚的是x_t具有强制性的第一个参数. (例如,这是不允许使用f()的原因).但这不是那么重要,修复很容易.问题仍然存在:为什么?

As for why not writing as x_fix_t with the first variant it is more clear that x_t has a mandatory first argument. (for instance that is the reason f() is not permitted). But this is not that important, the fix is easy. The question remains: Why?

gcc错误:

error: pack expansion argument for non-pack parameter ‘T’ of
alias template ‘template<class T, class ... Args> using x_t = typename x::type’

c语错误:

error: pack expansion used as argument for non-pack parameter of
alias template   x_t<Args...> v2;

推荐答案

它在GCC 4.8中编译,但在GCC 4.9中失败,这证明它与DR1430和

This compiles in GCC 4.8 but fails in GCC 4.9, which is evidence that it's related to DR1430 and bug report #59498. The fix proposed by Roy Chrihfield is the exact same one as yours:

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;

此外,Jason Merrill详细说明了失败的原因:

Furthermore, Jason Merrill elaborates on why it should fail:

实际上,不,这很大程度上是Core 1430的问题.没有办法 mangle variadic_alias不提及别名 模板中,它们应该完全是 透明的.这仅在4.8中偶然起作用,因为检查是 禁止发布.

Actually, no, this is very much a Core 1430 issue; there's no way to mangle variadic_alias without mentioning the name of an alias template in the mangling, and they're supposed to be entirely transparent. This only works in 4.8 by accident because checking is disabled for the release.

错误报告中没有进一步的讨论,因此我们可以转向DR1430:

No further discussion exists in the bug report, so we can turn to DR1430:

最初,包装扩展无法扩展为固定长度 模板参数列表,但是在N2555中已更改.这有效 适用于大多数模板,但会导致别名模板出现问题.

Originally, a pack expansion could not expand into a fixed-length template parameter list, but this was changed in N2555. This works fine for most templates, but causes issues with alias templates.

在大多数情况下,别名模板是透明的.当用于 模板,我们可以替换为从属模板参数. 但是,如果template-id对以下内容使用了包扩展名,则此方法不起作用 非可变参数.例如:

In most cases, an alias template is transparent; when it's used in a template we can just substitute in the dependent template arguments. But this doesn't work if the template-id uses a pack expansion for non-variadic parameters. For example:

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替代为止,因此它 需要进行整形处理.

There is no way to express A in terms of S, so we need to hold onto the A until we have the Ts to substitute in, and therefore it needs to be handled in mangling.

当前,EDG和Clang拒绝了这个测试用例,也抱怨 A的几个模板参数也是如此.但是我认为那是 一个错误.但是,在ABI名单上,约翰·斯派塞(John Spicer)认为应该 拒绝了.

Currently, EDG and Clang reject this testcase, complaining about too few template arguments for A. G++ did as well, but I thought that was a bug. However, on the ABI list John Spicer argued that it should be rejected.

(另请参见问题1558.)

(See also issue 1558.)

2012年10月会议的注意事项:

CWG的共识是应禁止这种用法, 当从属参数不能使用别名模板时,不允许使用 只需直接替换为type-id.

The consensus of CWG was that this usage should be prohibited, disallowing use of an alias template when a dependent argument can't simply be substituted directly into the type-id.

补充说明,2013年4月:

再举一个例子,请考虑:

For another example, consider:

  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>({});
  }

此示例的处理过程中存在实现差异.

There is implementation variance in the handling of this example.

换句话说,这是一个持续的问题,没有任何解决方案(AFAIC).

In otherwords, this is an on-going issue without any resolution (AFAIC) in sight.

这篇关于别名模板的包扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆