2017-11-18 19 views
2

これは私に悩まされています。明らかに私は何かを逃したので、誰かがそれが何であるか教えてくれることを願っています。shared_from_this()はstd :: shared_ptrを返します。<const X>ではなくstd :: shared_ptr <X>

私はC++ 17ライブラリを開発しています。私はNodeオブジェクトとカスタム反復子、Node::iteratorからなるカスタムツリーデータ構造を作成しました。私は親クラスTreeに標準イテレータ法(begin()end()、およびconstの同等物)を追加すると

template class NodeIterator<Node>; 
template class NodeIterator<const Node>; 

、私はできる...

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. 
} 

以降:イテレータはこのようになりますイテレータの初期値を制御します。だから私は_rootstd::shared_ptr<Node>ある

Node::iterator Tree::begin() const { 
    return Node::iterator(_root); 
} 

を言うことができます。これは素晴らしいです。

しかし、コンテンツだけでは十分ではありませんが、私はこれらのイテレータメソッドをノード自体に必要とします。そうすれば、どのノードからもサブツリーをたどることができ、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. 
} 

を宣言して、大声でreturn声明文句

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); 
} 

としてコンパイラをイテレータメソッドを定義します。

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); 
     ^

別の方法では、では、親ノード(std::shared_ptr<Node>)を自動的にthis->shared_from_this()に設定しても問題なく動作します。

私がNode::begin()Node::end()をコメントアウトし、私のループにcbegin()cend()しか使用しないと、うまくいきます。

何がありますか?

+0

メンバ関数のうちの1つが 'const'であり、もう1つはそうではありませんか? –

答えて

4

shared_from_thisには、constおよびnon-constのオーバーロードがあります。 cppreferenceを参照してください。あなたのconst beginの中で、thisはconstを指すポインタであり、constにオーバーフローを呼び出してshared_ptrをconstに返します。

+0

質問を更新して、イテレータメソッドを宣言し定義する方法についてもう少し詳細を追加しました。あなたは、あなたの提案されたソリューションがどんなものかについてもう少し詳しく知ることができますか? –

+2

@MatthewRatzloff 'begin()const'は' const_iterator'を返し、 'begin()'(非const)は 'iterator'を返します。 constオブジェクトを反復処理することでconstオブジェクトを変更できることは悪いことです。 –

+0

@ChrisDoddありがとう!私は間違いなく 'cbegin()'と 'cend()' *は定数定数(vector、list、map ...)であると考えました。あなたが 'begin()'と 'end()'をちょうどオーバーロードすることになっていたことに気付かなかった。そして、私の脳は明らかにそれらの両方の終わりにconstを歪んでいました。 –

関連する問題