shared_from_this()返回std :: shared_ptr <const X>,而不是std :: shared_ptr <X>

Mat*_*off 2 c++ iterator shared-ptr c++11

好吧,这个让我难过.很明显我错过了什么,所以我希望有人可以告诉我它是什么.

我正在开发一个C++ 17库.我编写了一个由Node对象和自定义迭代器组成的自定义树数据结构Node::iterator,用于遍历树.迭代器看起来像这样:

template <typename T>
class NodeIterator {
public:
    using value_type = T;
    using difference_type = std::ptrdiff_t;
    using pointer = std::shared_ptr<T>;
    using reference = T&;
    using iterator_category = std::forward_iterator_tag;

    NodeIterator() = default;
    NodeIterator(pointer n);

    // Etc.
}
Run Code Online (Sandbox Code Playgroud)

然后...

template class NodeIterator<Node>;
template class NodeIterator<const Node>;
Run Code Online (Sandbox Code Playgroud)

当我将标准迭代器方法(begin(),end()和const等价物)添加到父类时Tree,我可以控制迭代器的初始值.所以我可以说

Node::iterator Tree::begin() const {
    return Node::iterator(_root);
}
Run Code Online (Sandbox Code Playgroud)

这里_root是一个std::shared_ptr<Node>.这非常有效.

但是,不满足于单独留下足够好,我想在节点本身上使用这些迭代器方法.这样我就可以从任何节点遍历一个子树,Tree完全消除该类,并只传递Node对象.

我声明Node

class Node : public std::enable_shared_from_this<Node> {
public:
    using iterator = NodeIterator<Node>;
    using const_iterator = NodeIterator<const Node>;

    iterator begin() const;
    iterator end() const;
    const_iterator cbegin() const;
    const_iterator cend() const;

    // Etc.
}
Run Code Online (Sandbox Code Playgroud)

并将迭代器方法定义为

Node::iterator Node::begin() const {
    return Node::iterator(this->shared_from_this());
}

Node::iterator Node::end() const {
    return Node::iterator(nullptr);
}

Node::const_iterator Node::cbegin() const {
    return Node::const_iterator(this->shared_from_this());
}

Node::const_iterator Node::cend() const {
    return Node::const_iterator(nullptr);
}
Run Code Online (Sandbox Code Playgroud)

然后编译器大声抱怨return声明:

src/node.cc:79:9: error: no matching conversion for functional-style cast from
      'shared_ptr<const Node>' to 'Node::iterator' (aka 'NodeIterator<Node>')
        return Node::iterator(this->shared_from_this());
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

然后...

include/example.h:344:2: note: candidate constructor not viable: no known
      conversion from 'shared_ptr<const Node>' to 'shared_ptr<Node>' for
      1st argument
        NodeIterator(pointer n);
        ^
Run Code Online (Sandbox Code Playgroud)

在另一种方法中Node::appendChild(),我自动将父节点(std::shared_ptr<Node>)设置为this->shared_from_this(),并且它工作正常.

如果我注释掉Node::begin(),并Node::end()与只使用cbegin()cend()在我的循环,它也能正常工作.

是什么赋予了?

Jef*_*ett 5

shared_from_this有const和非const重载.见cppreference.在你的const中begin,this是指向const的指针并调用const重载,它返回一个shared_ptrconst.

  • @MatthewRatzloff让`begin()const`返回一个`const_iterator`和`begin()`(非const)返回一个`iterator`,就像它们应该的那样.能够通过迭代来修改const对象会很糟糕. (2认同)