OK, dieser hat mich ratlos. Offensichtlich habe ich etwas verpasst, also hoffe ich, dass mir jemand sagen kann, was es ist.Shared_from_this() gibt std :: shared_ptr zurück <const X>, nicht std :: shared_ptr <X>
Ich entwickle eine C++ 17-Bibliothek. Ich habe eine benutzerdefinierte Baumdatenstruktur geschrieben, bestehend aus Node
Objekten und einem benutzerdefinierten Iterator, Node::iterator
, um den Baum zu durchlaufen. Der Iterator sieht wie folgt aus:
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.
}
Und später ...
template class NodeIterator<Node>;
template class NodeIterator<const Node>;
Als ich den Standard Iteratormethoden (begin()
, end()
und die const Äquivalente) zu einer Klasse Eltern hinzufügen Tree
, kann ich Kontrolliere den Anfangswert für den Iterator. So kann ich sagen
Node::iterator Tree::begin() const {
return Node::iterator(_root);
}
wo _root
ein std::shared_ptr<Node>
ist. Das funktioniert großartig.
Allerdings nicht zufrieden genug zu verlassen, ich möchte diese Iterator-Methoden auf dem Knoten selbst. Auf diese Weise kann ich einen Teilbaum von einem beliebigen Knoten durchqueren, die Klasse Tree
komplett eliminieren und einfach Node
Objekte weitergeben.
Ich erkläre Node
als
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.
}
und die Iteratormethoden als
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);
}
Der Compiler definieren dann laut beschwert sich über die return
Aussage:
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());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
und später ...
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);
^
In einer anderen Methode, , setze ich automatisch den Elternknoten (std::shared_ptr<Node>
) auf this->shared_from_this()
, und es funktioniert gut.
Wenn ich Node::begin()
und Node::end()
kommentieren und nur cbegin()
und cend()
in meiner Schleife verwenden, funktioniert es auch in Ordnung.
Was gibt?
Vermutlich ist eine Ihrer Mitgliedsfunktionen "const" und die andere nicht? –