首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >作为模板参数的可变模板别名

作为模板参数的可变模板别名
EN

Stack Overflow用户
提问于 2013-11-28 05:32:02
回答 1查看 3.5K关注 0票数 17

首先是一些代码,然后是一些上下文,然后是问题:

代码语言:javascript
复制
template <typename T> using id = T;

template <template <typename...> class F, typename... T>
using apply1 = F <T...>;

template <template <typename...> class F>
struct apply2
{
    template <typename... T>
    using map = F <T...>;
};

// ...

cout << apply1 <id, int>() << endl;
cout << apply2 <id>::map <int>() << endl;

clang 3.3和gcc 4.8.1都对此进行了正确的编译,并将标识元函数应用于int,因此这两个表达式的计算结果都是默认的int (零)。

idtemplate <typename>,而apply1apply2 expect是template <typename...>,这一事实从一开始就让我担心。然而,这个例子运行起来非常方便,因为否则像apply1apply2这样的元函数就会涉及到更多的东西。

另一方面,这样的模板别名在现实世界的代码中会导致严重的问题,我不能在这里重现这些问题:频繁的内部编译器错误,以及不太频繁的clang的意外行为(仅在更高级的SFINAE测试中)。

经过几个月的试验和错误,我现在在(实验性的) gcc 4.9.0上安装和试用代码,错误来了:

代码语言:javascript
复制
test.cpp: In instantiation of ‘struct apply2<id>’:
test.cpp:17:22: error: pack expansion argument for non-pack parameter ‘T’ of alias template ‘template<class T> using id = T’
  using map = F <T...>; 
                      ^

好的,看起来这个代码并不总是有效的,但是gcc却以各种方式崩溃了,而不是报告这个错误。有趣的是,虽然apply1apply2看起来是等效的,但只为apply2报告了错误(这在实践中更有用)。至于clang,我真的不能说。

在实践中,我似乎别无选择,只能使用gcc 4.9.0并更正代码,即使它会变得更加复杂。

从理论上讲,我想知道标准是怎么说的:这段代码有效吗?如果不是,apply1的使用也是无效的吗?或者只使用apply2

编辑

只是为了澄清一下,到目前为止我遇到的所有问题都是模板别名,而不是模板结构。例如,考虑以下修改:

代码语言:javascript
复制
template <typename T> struct id1 { using type = T; };

// ...

cout << typename apply1 <id1, int>::type() << endl;
cout << typename apply2 <id1>::map <int>::type() << endl;

这两种情况下都能很好地编译并打印0,在clang 3.3、gcc 4.8.1、gcc 4.9.0上。

在大多数情况下,我的变通方法是在别名之前引入一个中间模板结构。然而,我现在正在尝试使用元函数来参数化通用SFINAE测试,在这种情况下,我必须直接使用别名,因为结构不应该被实例化。为了获得一个概念,实际代码的一部分是here

EN

回答 1

Stack Overflow用户

发布于 2013-11-29 08:24:19

ISO C++11 14.3.3/1:

模板模板参数的模板参数应该是类模板或别名模板表达式的名称,表示为id-

另外,对于可变模板模板参数,我没有看到任何特殊的异常。

另一方面,这样的模板别名在现实世界的代码中会导致严重的问题,我不能在这里重现:频繁的内部编译器错误,

的意外行为较少(仅在更高级的SFINAE测试中)。

问题的根源可能在其他地方。你应该尝试本地化导致内部编译器错误的代码--只需一个接一个地删除不相关的部分(或者使用某种二进制搜索,即分而治之)-并检查错误是否仍然存在于每个阶段。

至于GCC 4.9.0错误,请尝试更改

代码语言:javascript
复制
template <typename... T>
using map = F <T...>;

代码语言:javascript
复制
template <typename... U>
using map = F <U...>;

也许这将有助于理解GCC所看到的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20253473

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档