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;
  }

のようにしてもほぼ同じ結果になる.