可变变量模板类的部分专门化是否有利于非可变变量专门化
Should partial specialization of variadic template classes favor non-variadic specializations
我想知道用于构建例如元组的经典递归模式是否应该使用一个常规模板参数还是需要两个参数。下面是单参数的情况:
// Forward declaration of main tuple class template.
template<typename... Ds> class Tuple;
// Tuple class specialization for the general case
template<typename D, typename... Ds> class Tuple<D, Ds...> {
public:
typedef D HeadType;
typedef Tuple<Ds...> TailType;
Tuple() {}
Tuple(const D& head, const Ds&... ds) : mHead(head), mTail(ds...) {}
HeadType mHead;
TailType mTail;
};
// Sentinel one element case
template<typename D> class Tuple<D> {
public:
typedef D HeadType;
Tuple() {}
Tuple(const D& d) : mHead(d) {}
HeadType mHead;
};
在这里,你可以争辩说,当使用一个模板形参:Tuple<int>
实例化(直接或递归)时,两个特化都是有效的,声明应该是不明确的。然而,VS2012 Nov CTP接受这个代码,所以我不知道它是否可以,或者如果编译器只是很好。我没能在标准文本中找到任何提到这种情况的段落,但它确实很方便编译,并且在某种程度上逻辑上"更具体"的非可变专门化获胜。
// Forward declaration of main tuple class template.
template<typename... Ds> class Tuple;
// Tuple class specialization for the general case
template<typename D, typename D2, typename... Ds> class Tuple<D, D2, Ds...> {
public:
typedef D HeadType;
typedef Tuple<D2, Ds...> TailType;
Tuple() {}
Tuple(const D& head, const D2& d2, const Ds&... ds) : mHead(head), mTail(d2, ds...) {}
HeadType mHead;
TailType mTail;
};
// Sentinel one element case
template<typename D> class Tuple<D> {
public:
typedef D HeadType;
Tuple() {}
Tuple(const D& d) : mHead(d) {}
HeadType mHead;
};
遗憾的是,这不能在VS2012 Nov CTP上编译,但这肯定是一个错误:对mTail的tor调用不理解当第一个特化用两个类型调用时空参数包是空的…
所以主要问题仍然是:第一个版本是有效的c++吗?
如果有人能指出我在第二种选择中的错误,请帮忙!
在这里,你可以争辩说,当使用一个模板形参:
Tuple<int>
实例化(直接或递归)时,两个特化都是有效的,声明应该是不明确的。
根据目前的标准,是的,这确实应该是模棱两可的。请看这个缺陷报告。然而,该委员会表示,为了使非可变变量的排名优于可变变量,甚至也依赖于在当前标准中的排名。我将方便地链接到我的另一个答案,其中包含一个例子。
现在,基本上所有好的编译器都已经实现了这个DR的分辨率,而且它们必须这样做,否则std::common_type
就会被破坏(如果按照指定的定义)。从某种意义上说,编译器对你很好,但这是有原因的。
这个,遗憾的是,不能在VS2012 Nov CTP上编译,但这肯定是一个错误
是的,这是一个bug, 11月的CTP被认为是非常的bug。当我摆弄它的时候,那天晚上我提交了11个可变的bug(加上3个decltype bug,我想)。
您是否尝试对空元组版本进行专门化?在我的类型列表实现中,我总是这样做:
template<typename... T>
struct Tuple;
template<typename HEAD , typename... TAIL>
struct Tuple<HEAD,TAIL...>
{
using mHead = HEAD;
using mTail = typename std::enable_if<sizeof...(TAIL) > 0,Tuple<TAIL...>>::type;
...
};
template<>
struct Tuple<>
{
static_assert(false , "Empty tuples are not valid tuples");
};
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 你能重载对象变量名本身返回的内容吗
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 尝试通过多个向量访问变量时,向量下标超出范围
- SFINAE的变分变量模板专门化
- 为什么我必须专门化递归模板变量
- 在GCC中专门化静态类变量时出错:枚举示例
- 专门化时对静态成员变量的未定义引用
- 成员模板变量专门化
- 存储在变量模板专门化中的Spirit-X3解析器在Clang上不起作用
- 可变变量模板类的部分专门化是否有利于非可变变量专门化
- 头文件中模板专门化的静态变量初始化