迭代器的元组。 operator ++的实现

时间:2014-06-05 08:17:50

标签: c++ c++11

我正在维护一个std::tuple迭代器来实现类似压缩迭代器的东西。

template <typename... Args>
class ZipIterator {
public:
    typedef typename std::tuple< typename std::decay<Args>::type::iterator ... > IteratorTuple ;

    ZipIterator( const Args&... args ) : 
        tuple( args.begin() ... ){} ;

private:
    IteratorTuple tuple ;
} ;

template <typename... Args>
ZipIterator<Args...> zip( Args&&... args ){
    return ZipIterator<Args...>( args... ) ;    
}

现在我想实现迭代器操作,例如operator++。基本思想是ZipIterator::++只是++元组中托管的所有迭代器。到目前为止我所拥有的是:

template<int ...>
struct sequence {};

template<int N, int ...S> 
struct gens : gens<N-1, N-1, S...> {};

template<int ...S> 
struct gens<0, S...>{ 
    typedef sequence<S...> type; 
};

template<typename... Args>
struct index_sequence {
    typedef typename gens<sizeof...(Args)>::type type ;
} ;

template <typename... Args>
class ZipIterator {
public:
    typedef typename std::tuple< typename std::decay<Args>::type::iterator ... > IteratorTuple ;
    typedef typename std::tuple< typename std::decay<Args>::type::iterator::value_type ... > ValueTuple ;
    typedef typename index_sequence<Args...>::type Sequence ;

    ZipIterator( const Args&... args ) : 
        tuple( args.begin() ... ){} ;

    ZipIterator& operator++(){
        increment_all( Sequence() ) ;
        return *this ;
    }

    ValueTuple operator*(){
        return deref( Sequence() ) ;    
    }

private:

    template <typename... Pack>
    void nothing( Pack... ){}

    template <int... S>
    void increment_all(sequence<S...>) {
        nothing( increment<S>()... ) ;    
    }

    template <int S>
    typename std::tuple_element<S,IteratorTuple>::type increment(){
        return ++std::get<S>(tuple) ;
    }

    template <int... S>
    ValueTuple deref( sequence<S...> ){
        return ValueTuple( *std::get<S>(tuple) ... ) ;    
    }

    IteratorTuple tuple ;
} ;

template <typename... Args>
ZipIterator<Args...> zip( Args&&... args ){
    return ZipIterator<Args...>( args... ) ;    
}

我想提请注意这一部分:

    template <typename... Pack>
    void nothing( Pack... ){}

    template <int... S>
    void increment_all(sequence<S...>) {
        nothing( increment<S>()... ) ;    
    }

    template <int S>
    typename std::tuple_element<S,IteratorTuple>::type increment(){
        return ++std::get<S>(tuple) ;
    }

所以我现在所做的就是从increment返回一些内容,然后将其发送到nothing函数中,该函数不执行任何操作。还有另一种方式,例如我试过了:

    template <int... S>
    void increment_all(sequence<S...>) {
        { increment<S>()... ; } ;    
    }

但我明白了:

file5e1e684094e9.cpp:51:29: error: expected ';' after expression
            { increment<S>() ... ; } ;
                            ^
                            ;
file5e1e684094e9.cpp:51:15: error: expression contains unexpanded parameter pack 'S'
            { increment<S>() ... ; } ;
              ^         ~
file5e1e684094e9.cpp:51:30: error: expected expression
            { increment<S>() ... ; } ;
                             ^

我也有:

    template <int... S>
    void increment_all(sequence<S...>) {
        std::make_tuple( increment<S>() ... ) ;
    }

但这似乎是浪费,因为我根本不打算使用元组。事实上,我想要一个可以increment返回void的解决方案。

编辑:

基于各种评论,我现在有了这个,在预处理器的帮助下。

    #define DO_PREFIX(PREFIX) nothing( ( PREFIX std::get<S>(tuple) , 0 )... )
    #define DO_SUFFIX(SUFFIX) nothing( ( std::get<S>(tuple) SUFFIX , 0 )... )

    template <int... S>
    void increment_all(sequence<S...>) {
        DO_PREFIX(++) ;
    }

    template <int... S>
    void decrement_all(sequence<S...>) {
        DO_PREFIX(--) ;
    }

    template <int... S>
    void increment_all(int n, sequence<S...>) {
        DO_SUFFIX(+=n) ;
    }

    template <int... S>
    void decrement_all(int n, sequence<S...>) {
        DO_SUFFIX(-=n) ;
    }

1 个答案:

答案 0 :(得分:2)

我会在此示例中使用enable_if实现它:

#include <vector>
#include <tuple>
#include <type_traits>

template <typename... Args>
class ZipIterator {
  public:
    typedef typename std::tuple< typename std::decay<Args>::type::iterator ... > IteratorTuple ;
    typedef typename std::tuple< typename std::decay<Args>::type::iterator::value_type ... > ValueTuple ;

    ZipIterator( const Args&... args ) :
      tuple( args.begin() ... ){} ;

    ZipIterator& operator++(){
      increment_all<0>();
      return *this ;
    }

  private:
    template <unsigned Index>
    inline typename std::enable_if<(Index<sizeof...(Args)), void>::type increment_all(){
      ++std::get<Index>(tuple);
      increment_all<Index+1>();
    }

    template <unsigned Index>
    inline typename std::enable_if<(sizeof...(Args)<=Index), void>::type increment_all()
    {}

    IteratorTuple tuple ;
};

template <typename... Args>
ZipIterator<Args...> zip( Args&&... args ){
  return ZipIterator<Args...>( args... ) ;
}

int main() {
  std::vector<int> v1 {{1, 2, 3, 4}};
  std::vector<double> v2 {{1, 2, 3, 4}};

  auto zipped = zip(v1,v2);
  ++zipped;
  return 0;
}

dummy技巧有效,但看起来不合适。