一連の属性を管理するコンテナがあります。クラスは部分的に次のようになります。
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 にこのクラスのようなものはありますか?
私は他のアイデアを受け入れます。