2

この例が冗長であることをお詫びします。プロジェクトから考案したものです。コメントされた項目 1 と項目 2 は、次のコードで重要です。

#include <boost/intrusive/set.hpp>

struct x : public boost::intrusive::set_base_hook<>
{
    int y;
};

struct finder
{
    bool operator()(const int & i, const x & _x) const
    { return i < _x.y;}
    bool operator()(const x & _x, const int & i) const
        { return _x.y < i;}
};

class trampoline
{
public:
    void bounce() const /* item 1 */
    {
        /*item 2*/
        boost::intrusive::set<x>::iterator it = _set.find(1,finder()); 
    }

    boost::intrusive::set<x> _set;
};

int main()
{
    trampoline t;
    t.bounce();
}

スコープ内の関数が const であるメンバ コンテナ (アイテム 2) に非 const イテレータを使用することはできません。イテレータを const_iterator に切り替えるとすべて正常に動作するか、囲んでいる関数を非 const にすると同様に動作します. 次のエラー メッセージから問題を 1 時間リバース エンジニアリングした後、今では完全に理にかなっています。

test.cc: メンバー関数 'void トランポリン::bounce() const':test.cc:21: エラー: 'boost::intrusive::tree_iterator<boost::intrusive::rbtree_impl<boost::intrusive: からの変換: :setopt<boost::intrusive::detail::base_hook_traits<x, boost::intrusive::rbtree_node_traits<void*, false>, (boost::intrusive::link_mode_type)1u, boost::intrusive::default_tag, 3 >, std::less<x>, long unsigned int, true> >, true>' を非スカラー型 'boost::intrusive::tree_iterator<boost::intrusive::rbtree_impl<boost::intrusive::setopt <boost::intrusive::detail::base_hook_traits<x, boost::intrusive::rbtree_node_traits<void*, false>, (boost::intrusive::link_mode_type)1u, boost::intrusive::default_tag, 3>, std::less<x>, long unsigned int, true> >, false>' リクエスト

最終的に、次のテンプレート定義にたどり着きました (/include/boost/intrusive/detail/tree_node.hpp +72):

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
//                   Implementation of the tree iterator                   //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

// tree_iterator provides some basic functions for a 
// node oriented bidirectional iterator:
template<class Container, bool IsConst>

それで十分だったので、すぐに問題を解決したと言います....

そのテンプレートIsConstは、囲んでいる関数のコールサイトからどのように渡されるのでしょうか? 私の脳は爆発する準備ができています(私が知っている限り、それは単純なことですが、私は当惑しています). 仕組みを説明するための段階的な実装を含む詳細な説明は役に立ちます。

C++ のテンプレート メカニズムの型推定/エイリアシングに関して同様の質問がここにあります。参考文献は高く評価されますが、知識に熟考する必要があります:D. この質問に答える忍耐力がある場合は、別の質問についての談話を作成してみてください。

4

2 に答える 2

1

そのように?

Foo<false> bar();
Foo<true> bar() const;
于 2011-03-16T17:26:16.177 に答える
1

の find() メンバー関数には、boost::intrusive::set単純に const と non-const のオーバーロードがあるのではないでしょうか? つまり、それは私がそれを行う方法です:

template <typename T /*...*/ >
class set {
  //... 
  public:
    template <bool isConst>
    class iterator {
      //....
    };
    iterator<true> find(/*..*/) const; //notice the const
    iterator<false> find(/*..*/);      //notice no const
};

これは本当にメタプログラミングの魔法ではなく、昔ながらの const-correctness です。

于 2011-03-16T17:27:34.630 に答える