optional_iterator
bjam_grammarをテストしていて、string_listのバグを見つけました。
hamigaki::bjam::string_list ls;
ls.begin() == ls.end(); // VC8のデバッグモードだとassert落ち
原因は、string_listが空の場合、begin()もend()も空(どのvectorの要素も指していない)のvector<string>::iteratorを返していて、これを比較に使っているためです。
とはいえ、これだけのために空のvectorをnewしておくのは無駄なので、反復子に手を加えることにしました。
<hamigaki/iterator/optional_iterator.hpp>
#include <boost/iterator/iterator_adaptor.hpp> namespace hamigaki { template<class Iterator> class optional_iterator : public boost::iterator_adaptor< optional_iterator<Iterator>, Iterator > { friend class boost::iterator_core_access; private: typedef optional_iterator<Iterator> self_type; typedef typename self_type::iterator_adaptor_ base_type; public: optional_iterator() : valid_(false) { } optional_iterator(Iterator it) : base_type(it), valid_(true) { } private: bool valid_; bool equal(const self_type& rhs) const { if (valid_) { if (rhs.valid_) return this->base() == rhs.base(); else return false; } else return !rhs.valid_; } }; } // namespace hamigaki
デフォルトコンストラクタで初期化されたoptional_iteratorは、どの要素も指していませんが、equal()で比較基準を変更することで、互いに等しくなるようになっています。
string_listの反復子はこれでラップするようにしました。