Boost logo

Boost :

From: Roland Richter (roland_at_[hidden])
Date: 2002-12-17 06:54:08


David A. Greene wrote:

> The fundamental problem is that it's inconvenient to iterate through a
> tuple. All we have is the get<> template to access tuple elements.
> Iterating is again conceptually simple -- just increment an index.
> But the fact that get<> is a template implies the index must be a
> compile-time constant, meaning we need a compile-time loop (or, if
> you prefer, programmer-controlled loop unrolling) to iterate.

  Iteration through a tuple is indeed not so simple, but *recursion*
  is, and you can do that at runtime.

  All you need is to get the head and the tail out of a tuple, and,
  in turn construct a tuple out of head and tail. Boost.Tuple provides
  that: "get_head()" and "get_tail()", although it is not mentioned
  in the docs (why?).

  I'm not sure whether I completely understand what you need (did I?),
  but here is how I'd do it. Anyway, the idea of "iterating" through
  a tuple - and also the spanning_iterator thing - sounds interesting.

   - Roland

#include <iostream>
#include <functional>

#include "boost/tuple/tuple.hpp"
using namespace boost::tuples;

// Executes op() on the first member of tuple t if that meets cond(),
// recurses into the tail of t otherwise.
template<class TupleT, class OpT, class CondT>
TupleT do_if_first( TupleT t, OpT op, CondT cond )
{
   typedef cons< typename TupleT::head_type,
                 typename TupleT::tail_type > cons_type;

   if( cond( t.get_head() ) )
   {
     return TupleT( cons_type( op( t.get_head() ), t.get_tail() ) );
   }
   else
   {
     return TupleT( cons_type( t.get_head(), do_if_first( t.get_tail(), op, cond ) ) );
   }
}

// Stops recursion.
template<class OpT, class CondT>
tuple<null_type> do_if_first( null_type t, OpT op, CondT cond )
{
   return tuple<null_type>();
}

void main()
{
   tuple<double,char,int> t1( 3.14, 'a', -5 );

   std::cout << t1.get_head() << std::endl
             << t1.get_tail().get_head() << std::endl
             << t1.get_tail().get_tail().get_head() << std::endl << std::endl;

   tuple<double, char, int > t2 =
     do_if_first( t1, bind2nd( multiplies<double>(), -2.0 ), bind2nd(less<double>(), 0) );

   std::cout << t2.get_head() << std::endl
             << t2.get_tail().get_head() << std::endl
             << t2.get_tail().get_tail().get_head() << std::endl;
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk