【发布时间】:2020-04-08 17:29:04
【问题描述】:
我一直在尝试使用unique_ptr 实现一个链表并为其添加一个迭代器。我遇到了一个特殊的问题。当我尝试使用迭代器在列表的第一个元素上使用 decltype 时,我收到关于 invalid type "T" 的错误。
有人能解释一下这个错误的根源吗?
以下是重现错误的示例。
#include <memory>
#include <iostream>
template<class T>
class MyListItr;
template<typename T>
class MyList {
private:
int _size;
friend class MyListItr<T>;
public:
class Node {
private:
T value;
public:
std::unique_ptr<MyList::Node> next{ nullptr };
Node() = delete;
Node(T& value) :value(value), next(nullptr) {};
Node(MyList<T>::Node& ref) :value(ref.value), next(std::move(ref.next)) {};
T getVal()const { return value; };
void setVal(T value) { this->value = value; };
~Node() {};
};
std::unique_ptr<MyList::Node> head;
MyList(const MyList<T>&) = delete;
MyList& operator=(const MyList<T>) = delete;
MyList() :_size(0), head(nullptr) {};
int size()const { return _size; };
void push_front(T);
T pop_front();
T front()const;
MyListItr<T> begin() {
typename MyList<T>::Node* tmp = this->head.get();
return MyListItr<T>::MyListItr(tmp);
};
MyListItr<T> end() { return MyListItr<T>::MyListItr(nullptr); };
typedef MyListItr<T> iterator;
typedef T value_type;
typedef T* pointer;
typedef std::ptrdiff_t difference_type;
typedef T& reference;
typedef size_t size_type;
};
template<typename T>
class MyListItr : public std::iterator<std::output_iterator_tag, T> {
typename MyList<T>::Node* data;
public:
MyListItr(typename MyList<T>::Node* data) :data(data) {}
bool operator!=(MyListItr<T>const& T)const;
MyListItr<T> operator++();
T operator*();
};
template<typename T>
void MyList<T>::push_front(T x) {
std::unique_ptr<MyList::Node>tmp = std::move(this->head);
this->head = std::make_unique<MyList<T>::Node>(MyList<T>::Node(x));
this->head->next = std::move(tmp);
_size++;
};
template<typename T>
T MyList<T>::pop_front() {
if (this->_size == 0)throw std::out_of_range("Range exceeded");
T tmp = this->head.get()->getVal();
this->head = std::move(this->head->next);
_size--;
return tmp;
};
template<typename T>
T MyList<T>::front()const {
return this->head.get()->getVal();
};
template<typename T>
bool MyListItr<T>::operator!=(MyListItr<T>const& Itr)const {
return this->data != Itr.data;
};
template<typename T>
MyListItr<T> MyListItr<T>::operator++() {
return(this->data->next.get());
};
template<typename T>
T MyListItr<T>::operator*() {
return (this->data->getVal());
};
int main() {
MyList<int> l;
l.push_front(4);
std::cout<< *l.begin();
std::cout << decltype(*l.begin());
return 0;
}
【问题讨论】:
-
您是否使用
std::cout << decltype(*l.begin());尝试打印出对象类型? -
你期望代替
T的是什么? 为什么? -
你不能
std::cout得到decltype的结果,就像你可以做std::cout << int;一样。 -
坦率地说,您似乎误解了
decltype的作用。要澄清这一点,您需要解释您认为它的作用。 -
好的,所以我不知道你不能打印它,并认为它重现了我想要显示的相同错误,即调用
std::is_same_v<decltype(*l.begin()), int&>返回 false,我期待它返回 true,因为 elemtn 访问的是 int