shared_from_this() returns std::shared_ptr<const X>, 不是 std::shared_ptr<X>
shared_from_this() returns std::shared_ptr<const X>, not std::shared_ptr<X>
好吧,这个让我难住了。显然我错过了什么,所以我希望有人能告诉我它是什么。
我正在开发 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.
}
后来……
template class NodeIterator<Node>;
template class NodeIterator<const Node>;
当我将标准迭代器方法(begin()
、end()
和 const 等价物)添加到父 class Tree
时,我可以控制初始值对于迭代器。所以我可以说
Node::iterator Tree::begin() const {
return Node::iterator(_root);
}
其中 _root
是 std::shared_ptr<Node>
。这很好用。
但是,我不满足于单独使用这些迭代器方法,我想在节点本身上使用这些迭代器方法。这样我就可以从任何节点遍历子树,完全消除 Tree
class,只传递 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.
}
并将迭代器方法定义为
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);
}
然后编译器大声抱怨 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());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以后...
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);
^
另一种方法Node::appendChild()
,我自动将父节点(std::shared_ptr<Node>
)设置为this->shared_from_this()
,效果很好。
如果我注释掉 Node::begin()
和 Node::end()
并且只在我的循环中使用 cbegin()
和 cend()
,它也可以正常工作。
什么给了?
shared_from_this
有 const 和非常量重载。参见 cppreference。在您的 const begin
中,this
是指向 const 的指针,并调用 const 重载,其中 returns 一个 shared_ptr
到 const.
好吧,这个让我难住了。显然我错过了什么,所以我希望有人能告诉我它是什么。
我正在开发 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.
}
后来……
template class NodeIterator<Node>;
template class NodeIterator<const Node>;
当我将标准迭代器方法(begin()
、end()
和 const 等价物)添加到父 class Tree
时,我可以控制初始值对于迭代器。所以我可以说
Node::iterator Tree::begin() const {
return Node::iterator(_root);
}
其中 _root
是 std::shared_ptr<Node>
。这很好用。
但是,我不满足于单独使用这些迭代器方法,我想在节点本身上使用这些迭代器方法。这样我就可以从任何节点遍历子树,完全消除 Tree
class,只传递 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.
}
并将迭代器方法定义为
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);
}
然后编译器大声抱怨 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());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以后...
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);
^
另一种方法Node::appendChild()
,我自动将父节点(std::shared_ptr<Node>
)设置为this->shared_from_this()
,效果很好。
如果我注释掉 Node::begin()
和 Node::end()
并且只在我的循环中使用 cbegin()
和 cend()
,它也可以正常工作。
什么给了?
shared_from_this
有 const 和非常量重载。参见 cppreference。在您的 const begin
中,this
是指向 const 的指针,并调用 const 重载,其中 returns 一个 shared_ptr
到 const.