在Template类的Template Member函数中设置构造函数的首选项

时间:2017-05-31 00:55:12

标签: c++ c++11 templates constructor

我试图为学习目的创建我自己的双向链表实现。我想用模板类来做这件事。我有一些构造函数具有如下定义:

template <typename TYPE>
class DList {
public:
    DList(const size_t size, const TYPE& val = TYPE());

    template <typename ITER>
    DList(ITER&& begin, ITER&& end);
};

(我有更多代码,我省略了。)

第一个构造函数复制提供的大小时间值(因此DList<int>(5, 2)将复制数字2,5次)

第二个构造函数将范围(在2个迭代器之间)复制到列表中。 (因此DList<int>(other.begin(), other.end())会将一个数据结构复制到DList

问题是如何设置两个构造函数的首选项?例如,如果我用这一行实例化我的类:

DList<int> listTest2(6, 2);

编译器感到困惑,并在大小构造函数上选择基于迭代器的构造函数并抛出错误。我想保留模板迭代器构造函数,因为我有其他类(实现其他数据结构),迭代器是类中的类。 (所以DList里面有一个叫做迭代器的类,见下面有关我的意思的更多信息。

无论如何都要设置一个首选项来调用哪个构造函数。我希望它能像我如何调用std::vector<int>(other.begin, other.end)std::vector<int>(2, 3)一样工作。

我已经为我的模板类添加了头文件:

template <typename TYPE>
class DList {
public:
    struct Node {
        Node* prev;
        TYPE data;
        Node* next;
    };

    class iterator {
    public:
        iterator();
        iterator(const Node* node);
        iterator(const iterator& it);

        iterator& operator++(); // preincrement
        iterator& operator--();

        iterator operator++(int); // postincrement
        iterator operator--(int);

        iterator& operator=(const iterator& it);

        iterator& operator-(int scale);
        iterator& operator+(int scale);

        bool operator==(const iterator& it);

        TYPE& operator*();
        TYPE& operator->();

        Node* getNode();

    private:
        Node* data;

    };

    DList();
    DList(const DList& other);

    DList(const size_t size, const TYPE& val = TYPE());

    template <typename ITER>
    DList(ITER&& begin, ITER&& end);

    iterator begin() const;
    iterator end() const;

    void clear();

    void push_back(const TYPE& val);
    void push_front(const TYPE& val);

    void pop_back();
    void pop_front();

    void insert(size_t idx, const TYPE& val);
    void insert(const DList<TYPE>::iterator it, const TYPE& val);
    void remove(const TYPE& val);

    size_t size() const;

    const TYPE& operator[](size_t idx) const;
    TYPE& operator[](size_t idx);

private:    
    Node* mHead; /// @todo convert to iterators?
    Node* mTail;
    size_t mSize;

};

1 个答案:

答案 0 :(得分:1)

首先:用

观察
DList<int> listTest2(6, 2);

你调用了错误的构造函数,因为你传递了错误的第一个参数:size / val构造函数等待第一个参数的std::size_t,所以是无符号值。但是您发送6,这是签名值。

调用size / val构造函数的正确方法是

DList<int> listTest2(6U, 2);

二;你使用&&(rvalue)引用;所以你可以使用C ++ 11;所以你可以使用decltype

不是一个很好的解决方案,但如果您真的希望DList<int> (6, 2)调用size / val构造函数,则可以使用SFINAE并启用模板构造函数 ITER typename支持一元*操作时(访问指向值,由迭代器支持但不支持简单整数),所以

template <typename I, typename = decltype(*I{})>
DList (I && begin, I && end)

以下是一个完整的工作(最小)示例

#include <iostream>
#include <vector>

template <typename T>
struct DList
 {
   DList (std::size_t const size, T const & val = T{})
    { std::cout << "constructor 1" << std::endl; }

   template <typename I, typename = decltype(*I{})>
   DList (I && begin, I && end)
    { std::cout << "constructor 2" << std::endl; }
 };

int main()
 {
   std::vector<int> vi { 2, 3, 5, 7, 11, 13 };

   DList<int>(6, 2);                   // print constructor 1
   DList<int>(vi.cbegin(), vi.cend()); // print constructor 2
 }