c++ - 可变参数模板类的部分特化是否应该支持非可变参数特化

标签 c++ templates c++11 variadic-templates

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

// 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 的 ctor 调用不明白当使用两种类型调用第一个专门化时,空参数包为空...

所以主要问题仍然是:第一个版本是否有效的 C++?

如果有人可以指出我在第二种选择中的错误,请这样做!

最佳答案

Here you could argue that when instantiated (directly or in the recursion) with one template parameter: Tuple<int> that both specializations are valid and the declaration should be ambiguous.

按照目前的标准,是的,这确实应该是有歧义的。请参阅this defect report 。然而,委员会表示,非可变参数变体的排名要优于可变参数变体,甚至依赖当前标准中的这一点。我就方便地链接to another answer of mine其中包含一个示例。

现在,基本上所有好的编译器都已经实现了这个 DR 的解析,而且他们必须这样做,否则 std::common_type会被简单地破坏(如果按照指定定义)。所以,是的,从某种意义上说,编译器对你很好,但有充分的理由。

This, sadly, does not compile on VS2012 Nov CTP, but that is surely a bug

是的,这是一个错误,并且 11 月的 CTP 已知极其有错误。当我尝试使用它时,那天晚上我提交了 11 个可变错误(我想还有 3 个 decltype bug)。

关于c++ - 可变参数模板类的部分特化是否应该支持非可变参数特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15122854/

相关文章:

c++ - 使用智能指针间接将 std::array 插入堆

c++ - 两个字符串大小的差异

c++ - 我需要相互包含两个头文件而不使用前向声明导致出现 "incomplete type"错误

c++ - C++ 中的类型别名

C++:为什么 'delete' 内存比 'new' 内存慢太多

c++ - 如何让 for_each 使用模板?

模板破坏 http HEAD 方法

c++ - 类成员模板函数的名称实例

c++ - 将 weak_ptr 与原始指针进行比较不起作用,正在寻找替代方案

c++ - 陷阱无法捕获 SIGSEGV