【问题标题】:Why does decltype on value returned from template function return T为什么从模板函数返回的值上的decltype返回T
【发布时间】: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 &lt;&lt; decltype(*l.begin()); 尝试打印出对象类型?
  • 你期望代替T的是什么? 为什么?
  • 你不能std::cout 得到decltype 的结果,就像你可以做std::cout &lt;&lt; int; 一样。
  • 坦率地说,您似乎误解了 decltype 的作用。要澄清这一点,您需要解释您认为它的作用。
  • 好的,所以我不知道你不能打印它,并认为它重现了我想要显示的相同错误,即调用 std::is_same_v&lt;decltype(*l.begin()), int&amp;&gt; 返回 false,我期待它返回 true,因为 elemtn 访问的是 int

标签: c++ types


【解决方案1】:

decltype() 只为您提供:一种类型。不是字符串。您不能像尝试那样将类型流式传输到控制台。

如果你想获得某种类型的字符串表示,you can do that, though not in a portable fashion。

【讨论】:

  • 好的,我不知道,但是当我尝试执行 std::is_same_v&lt;decltype(*l.begin()), int&amp;&gt; 时,它返回 false,尽管列表创建为 所以
  • @KonradP 不要引用我的话(我正在处理多项任务),但在这种情况下可能是int,而不是int&amp;。请阅读some documentation!您的代码还有其他错误,这意味着我不能快速尝试它,这很遗憾。 minimal reproducible example 会更好。
  • @KonradP 不,它是int,而不是int&amp;,因为您的operator* 实现(错误地)返回T 而不是T&amp;。
  • 好的,我现在看到我的错误了,我确实返回了一个 int 而不是 int&,现在已经改变了 operator* 的工作方式,这很好,谢谢你的帮助。
猜你喜欢
  • 2019-01-08
  • 2022-12-21
  • 2021-02-05
  • 1970-01-01
  • 2017-11-25
  • 2014-09-03
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
相关资源
最近更新 更多