繰り返される値をどうしますか?
これが配列内のインデックスになる場合は、関連するクラスiterator
またはreverse_iterator
クラスを使用し、これらの周りにアルゴリズムを実装する必要があります。コードはより堅牢になり、保守や進化が容易になります。さらに、標準ライブラリの多くのツールは、これらのインターフェイスを使用して構築されています。
実際には、そうでない場合でも、独自のインデックスを返すイテレータクラスを実装できます。
メタプログラミングの魔法を少し使って、イテレータがとの順序に従ってどのように動作するかを定義することもできA
ますB
。
先に進む前に、これはとの定数値でのみ機能することを考慮してください。A
B
template <int A,int B>
struct ordered {
static const bool value = A > B ? false: true;
};
template <bool B>
int pre_incr(int &v){
return ++v;
}
template <>
int pre_incr<false>(int &v){
return --v;
}
template <int A, int B>
class const_int_iterator : public iterator<input_iterator_tag, const int>
{
int p;
public:
typedef const_int_iterator<A,B> self_type;
const_int_iterator() : p(A) {}
const_int_iterator(int s) : p(s) {}
const_int_iterator(const self_type& mit) : p(mit.p) {}
self_type& operator++() {pre_incr< ordered<A,B>::value >(p);return *this;}
self_type operator++(int) {self_type tmp(*this); operator++(); return tmp;}
bool operator==(const self_type& rhs) {return p==rhs.p;}
bool operator!=(const self_type& rhs) {return p!=rhs.p;}
const int& operator*() {return p;}
};
template <int A, int B>
class iterator_factory {
public:
typedef const_int_iterator<A,B> iterator_type;
static iterator_type begin(){
return iterator_type();
}
static iterator_type end(){
return iterator_type(B);
}
};
上記のコードでは、AからBの値にまたがるベアボーンiterator
クラスを定義しました。AとBが昇順であるかどうかを判断し、正しい演算子(++
または--
)を選択して値を調べる簡単なメタプログラミングテストがあります。
最後に、保持する単純なファクトリクラスbegin
とend
イテレータメソッドも定義しました。このクラスを使用すると、依存型の値AとBに対して単一の宣言ポイントのみを使用できます(ここでは、AとBを1回だけ使用する必要があります。このコンテナ、およびそこから生成されるイテレータは、これらの同じAとBに依存するため、コードがいくらか単純化されます)。
ここでは、20から11までの値を出力する簡単なテストプログラムを提供します。
#define A 20
#define B 10
typedef iterator_factory<A,B> factory;
int main(){
auto it = factory::begin();
for (;it != factory::end();it++)
cout << "iterator is : " << *it << endl;
}
ただし、標準ライブラリを使用してこれを行うためのより良い方法があるかもしれません。
との使用O
とUINT_MAX
のためA
の問題B
が提起されました。これらの特定の値を使用してテンプレートをオーバーロードすることで、これらのケースを処理できるはずだと思います(読者の演習として残しておきます)。