N整数変数のループ生成クラス
x, y をそれぞれ (0,49), (0,20) の範囲で繰り返したい場合は,2重に for ループを書けばよい.変数が x, y, z なら3重にforループを書く.NならN重ループ.このNが何らかの事情でコンパイル以前に決められない場合はどうしよう.
解決策はいくらでもあると思うが,すべての組合せを生成するクラスを書いてみた.
class TAllPair { public: typedef std::size_t value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef std::vector<value_type> set_type; typedef set_type::iterator iterator; typedef set_type::const_iterator const_iterator; typedef set_type::reverse_iterator reverse_iterator; typedef set_type::const_reverse_iterator const_reverse_iterator; private: set_type d, size; bool include_zero_size; public: template <typename InputIterator> TAllPair (InputIterator sizefirst, InputIterator sizelast) : include_zero_size(false) { for(InputIterator i(sizefirst); i!=sizelast; ++i) { size.push_back(*i); if (*i<=0) include_zero_size=true; } d.resize (size.size(), 0); }; iterator begin(void) {return d.begin();}; const_iterator begin(void) const {return d.begin();}; reverse_iterator rbegin(void) {return d.rbegin();}; const_reverse_iterator rbegin(void) const {return d.rbegin();}; iterator end(void) {return d.end();}; const_iterator end(void) const {return d.end();}; reverse_iterator rend(void) {return d.rend();}; const_reverse_iterator rend(void) const {return d.rend();}; reference operator[] (int i) {return d[i];}; const_reference operator[] (int i) const {return d[i];}; void init (void) {for(iterator itr(begin()); itr!=end(); ++itr) *itr=0;}; bool cont (void) const { if (include_zero_size) return false; if (d.back()>=size.back()) return false; else return true; }; bool step (void) { const_iterator sizeitr (size.begin()); for(iterator itr(begin()); itr!=end(); ++sizeitr,++itr) { if (*itr+1<*sizeitr) {++(*itr); break;} if (itr==end()-1) {*itr=*sizeitr;} else *itr=0; } return cont(); }; };
クラス名 TAllPair がすこぶる適当なのは置いておいて,
const int A[] = {2,3,3}; TAllPair a(A,A+sizeof(A)/sizeof(int)); a.init(); for (a.init(); a.cont(); a.step()) std::cout << a[0] << " : " << a[1] << " : " << a[2] << std::endl;
こんな感じで使えば,
0 : 0 : 0 1 : 0 : 0 0 : 1 : 0 1 : 1 : 0 0 : 2 : 0 1 : 2 : 0 0 : 0 : 1 1 : 0 : 1 0 : 1 : 1 1 : 1 : 1 0 : 2 : 1 1 : 2 : 1 0 : 0 : 2 1 : 0 : 2 0 : 1 : 2 1 : 1 : 2 0 : 2 : 2 1 : 2 : 2
みたいな結果が得られる.Aはstd::vectorでもok.
a[0]とかのアクセスがダサいとお考えなら,
const int A[] = {2,3,3}; for (TAllPair a(A,A+sizeof(A)/sizeof(int)); a.cont(); a.step()) { for (TAllPair::const_iterator itr(a.begin()); itr!=a.end(); ++itr) std::cout << " " << *itr; std::cout << std::endl; }
のようにしてもほぼ同じ結果になる.