8

私はこのコンテナを持っています:

class /*final*/ Row
{
public:
  typedef FieldIterator const_iterator;
  typedef FieldIterator iterator;
  FieldIterator begin() const;
  FieldIterator end() const;
  FieldIterator begin();
  FieldIterator end();
  ...
};

それを考えると、次のコードは問題なくコンパイルされます。

BOOST_FOREACH(Field field, row)
{
}

ただし、Rowクラスには変更可能なイテレータを含めるべきではないため、変更可能なアクセスを削除して Row クラスを変更しました。

class /*final*/ Row
{
public:
  typedef FieldIterator const_iterator;
  FieldIterator begin() const;
  FieldIterator end() const;
  ...
};

しかし、今度は同じ foreach ループがコンパイルに失敗します。

1>o:\c\boost_1_48_0\boost\foreach.hpp(364): error C2039: 'type' : is not a member of 'boost::mpl::eval_if<C,F1,F2>'
1>          with
1>          [
1>              C=boost::mpl::false_,
1>              F1=boost::range_const_iterator<sqlserver::Row>,
1>              F2=boost::range_mutable_iterator<sqlserver::Row>
1>          ]
1>          c:\dev\internal\playmssqlce\playmssqlce.cpp(29) : see reference to class template instantiation 'boost::foreach_detail_::foreach_iterator<T,C>' being compiled
1>          with
1>          [
1>              T=sqlserver::Row,
1>              C=boost::mpl::false_
1>          ]
...

エラーメッセージから、明らかに失敗BOOST_FOREACHする型をインスタンス化しようとしていることがわかります。range_mutable_iterator代わりに定数範囲をインスタンス化するにはどうすればよいですか?

ありがとう。

編集

と の完全なクラス宣言は次RowFieldIteratorとおりです。

class /*final*/ Row
{
  const BYTE *m_buffer;
  const DBBINDING *m_pColumnBindings;
  int m_columnBindingCount;
  FieldIterator m_end;
public:
  typedef FieldIterator const_iterator;
  typedef FieldIterator iterator;
  Row(const BYTE *buffer, const DBBINDING *pColumnBindings, int columnBindingCount);
  bool isSameRow(const Row& r) const;
  int fieldCount() const;
  Field field(int i) const;
  Field& field(int i, void *fieldBuffer) const;
  FieldIterator begin() const;
  FieldIterator end() const;
  FieldIterator begin();
  FieldIterator end();
};

class FieldIterator : public iterator_facade<FieldIterator, Field, boost::random_access_traversal_tag>
{
  const Row *m_pRow;
  int m_index;
  mutable BYTE m_fieldBuffer[sizeof(Field)];
public:
  FieldIterator(const Row *pRow = NULL, int index = 0);
private:
  friend class boost::iterator_core_access;
  void increment();
  void decrement();
  void advance(difference_type n);
  difference_type distance_to(FieldIterator it);
  reference dereference() const;
  bool equal(const FieldIterator& rhs) const;
};
4

4 に答える 4

6

本当にメンバーを避けたい場合の回避策iterator、イテレータのペアを使用することです。

BOOST_FOREACH(Field field, std::make_pair(row.begin(), row.end()))
于 2012-01-12T13:18:22.140 に答える
5

元のコードのどこが間違っていましたか?

std::setやなどの一部の標準ライブラリ コンテナには、std::multisetすべてが const のイテレータがあります (更新は許可されません)。この規格は具体的に次のように述べています。

値の型がキーの型と同じである連想コンテナーの場合、iterator と const_iterator の両方が定数反復子です。iterator と const_iterator が同じ型かどうかは未規定です。

あなたはおそらく逃げるでしょう

typedef const_iterator iterator;

あなたのクラスで。

于 2012-01-12T13:16:58.480 に答える
0

ブースト 1.52 (他のバージョンではテストしていません)BOOST_FOREACH(Field field, const_cast<Row const&>(row))でも動作します。

于 2013-03-24T23:51:00.153 に答える
0

FieldIteratorconst および非 const 反復子メソッドの同じ反復子クラスのようです。C スタイルの配列を含む任意のコンテナーで動作するため、問題はクラスBOOST_FOREACHにあると思われます。FieldIteratorコードを投稿できますか?

于 2012-01-12T13:15:21.293 に答える