6

一連の属性を管理するコンテナがあります。クラスは部分的に次のようになります。

class AttributeSet
{
public:
    // ... interface is irrelevant for my question.

private:
    std::vector<boost::shared_ptr<Attribute> > m_attributes;
};

属性は多態的であるため、属性はポインターとして格納する必要がありますが、NULL にすることはできません。

次のように、このクラスを BOOST_FOREACH で使用したいと考えています。

BOOST_FOREACH(const Attribute &attribute, attributeSet)
{
    ...
}

BOOST_FOREACH のドキュメントによると、

STL コンテナーのサポートは非​​常に一般的です。STL コンテナーのように見えるものはすべてカウントされます。ネストされた iterator および const_iterator 型と begin() および end() メンバー関数がある場合、BOOST_FOREACH はそれを反復する方法を自動的に認識します。

そこで、クラスを次のように更新しました。

class AttributeSet
{
public:
    typedef std::vector<boost::shared_ptr<Attribute> > container;
    typedef container::iterator iterator;
    typedef container::const_iterator const_iterator;

    iterator begin();
    iterator end();

    const_iterator begin() const;
    const_iterator end() const;

private:
    container m_attributes;
};

だから今私はこれを行うことができます:

BOOST_FOREACH(const boost::shared_ptr<Attribute> &attribute, attributeSet)
{
    ...
}

これはいいことですが、属性をポインターとして公開するのは好きではありません。呼び出し側からは、これはノイズであり、無意味な NULL チェックが生成されます。

問題を修正する方法についていくつかのアイデアがあります。たとえば、次のようなものがいいでしょう。

class AttributeSet
{
public:
    typedef std::vector<boost::shared_ptr<Attribute> > container;
    typedef iterator_dereference_adapter< container::iterator > iterator;
    typedef iterator_dereference_adapter< container::const_iterator > const_iterator;

    iterator begin() { return iterator(m_attributes.begin()); }
    iterator end() { return iterator(m_attributes.end()); }

    const_iterator begin() const { return const_iterator(m_attributes.begin()); }
    const_iterator end() const { return const_iterator(m_attributes.end()); }

private:
    container m_attributes;
};

「iterator_dereference_adapter」クラスは、ある程度自明です。ポインターの既存の反復子をラップし、ポインター値を逆参照します。

最後に、私の質問は...

このアダプターを作成する前に、STL または Boost にこのクラスのようなものはありますか?

私は他のアイデアを受け入れます。

4

1 に答える 1

8

Boost にはindirect_iteratorがあります。これは、反復子をポインター型にラップし、自動的に逆参照することを正確に意図しています。

于 2013-07-12T16:21:13.837 に答える