可变变量模板类的部分专门化是否有利于非可变变量专门化

Should partial specialization of variadic template classes favor non-variadic specializations

本文关键字:专门化 变量 是否 有利于      更新时间:2023-10-16

我想知道用于构建例如元组的经典递归模式是否应该使用一个常规模板参数还是需要两个参数。下面是单参数的情况:

// 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接受这个代码,所以我不知道它是否可以,或者如果编译器只是很好。我没能在标准文本中找到任何提到这种情况的段落,但它确实很方便编译,并且在某种程度上逻辑上"更具体"的非可变专门化获胜。

现在,如果这是不合适的c++ 11,下面的代码是一个替代,使用两个常规模板参数,使1参数的情况下不能选择一般专门化:
// 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");
};