我试图为学习目的创建我自己的双向链表实现。我想用模板类来做这件事。我有一些构造函数具有如下定义:
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;
};
答案 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
}