通过n元组迭代

时间:2014-07-16 20:46:36

标签: c++ iterator

是否有一种巧妙的方法来迭代n元组,其中元组中的每个元素都可以取k个值(总共k ^ n种可能性)。我猜测k = 2你可以通过递增十进制来迭代一个位数组。那个k的其他值怎么样?

在k可以取{-1,0,1}的情况下,我实际上是在C ++中专门寻找一种可能的方法。

1 个答案:

答案 0 :(得分:0)

template<class E, E...es>
struct elements:std::integral_constant<unsigned, sizeof...(es)> { using type=E; };

template<class E, E e0, E e1, E... es>
constexpr E next_helper( elements<E, e0, e1, es...>, E e, E first ) {
  return (e0 == e)?e1:next_helper( elements<E, e1, es...>{}, e, first );
}
template<class E, E e0>
constexpr E next_helper( elements<E, e0>, E e, E first ) {
  return first;
}
template<class E, E e0, E... es>
constexpr E next_helper( elements<E, e0, es...>, E e ) {
  return next_helper( elements<E, e0, es...>{}, e, e0 );
}
template<class elements, class E>
constexpr E next( E e ) {
  return next_helper( elements{}, e );
}
template<class elements, class E>
constexpr E next( E e, unsigned N );
template<class E, E...es>
constexpr E next_helper( elements<E,es...>, E e, unsigned N ) {
  return (N>=sizeof...(es))?next<elements>( e, (N%sizeof...(es)) ):next<elements>( next<elements>( e, (N)/2 ), (N+1)/2 );
}
template<class elements, class E>
constexpr E next( E e, unsigned N ) {
  return (N==0)?e:(N==1)?next<elements>(e):next_helper<elements>( next_helper<elements>( N/2, e ), (N+1)/2 );
}
template<class E, E e0, E e1, E... es>
constexpr unsigned index_helper( elements<E, e0, e1, es...>, E e ) {
  return (e0==e)?0:(index_helper( elements<E, e1, es...>{}, e )+1);
}
template<class E, E e0>
constexpr unsigned index_helper( elements<E, e0>, E e ) {
  return 0;
}
template<class elements, class E>
constexpr unsigned index( E e ) {
  return index_helper( elements{}, e );
}
template<class E, E e0, E... es>
constexpr unsigned first_helper(elements<E, e0, es...>) {
  return e0;
}
template<class elements>
constexpr auto first() -> typename elements::type {
  return first_helper(elements{});
}
template<class elements>
constexpr auto nth(unsigned n) -> typename elements::type {
  return next<elements>( first<elements>(), n );
}

template<typename elements>
struct iteration_tuple {
  using value_type = typename elements::type;
  std::vector<value_type> data;
  bool advance() {
    bool finished = true;
    for( value_type& e : data ) {
      if ( first<elements>() != ( e = next<elements>(e) ) )
        finished = false;
      if (!finished)
        break;
    }
    return finished;
  }
  iteration_tuple( unsigned size ) {
    data.resize( size, first<elements>() );
  }
};

int main() {
  typedef elements<int, -1, 0, 1> sequence;
  iteration_tuple<sequence> sample(3);
  do {
    for (int x:sample.data)
      std::cout << x << ",";
    std::cout << "\n";
  } while(!sample.advance());
}

live example