Hi,

The "for-each" in mpl is used to generate codes, which apply some function to each 
element in a sequence. Well, I wonder if there could be more generators, "select"(a 
better name?) for example. 

"select" is used to apply some function to a specified element in a sequence(the case 
in the FSM example, not each element). So it could be used to generate codes like the 
"if-else/switch" structure. Here's an example.

  #include <boost/mpl/range_c.hpp>
  #include "select.hpp"
  #include <boost/mpl/alias.hpp>

  struct find_helper {
  private:
    const double* X_;   // array
    const double& a_;   // element to be found
    int& pos_;          // result, position of the given element
  public:
    find_helper(const double* X, const double& a, int& pos)
        : X_(X), a_(a), pos_(pos) {}
    bool operator ()(int i)  
    {
        if(X_[i] == a_)
        {
            pos_ = i;
            return true;        // "true" means it's been handled
        }
        return false;           // "false" means to continue
    }
  };

  template <typename T, int N>
  struct find_element_c {
    static int do_(T* X, const T& a)
    {
        int r = N;
        mpl::select<                   // "select" returns true if
            mpl::range_c<int, 0, N>    //    the functor has been applied,
        >(find_helper(X, a, r));       // otherwise false.
        return r;
    }
  };

  #include <iostream>

  int main()
  {
    double X[5] = {1.0, 2.1, 3.5, 6.6, 5.4};
    std::cout << find_element_c<double, 5>::do_(X, 3.5) << std::endl;
  }

output: 2

The generated code might look like:

  if(X[0] == 3.5)
    return 0;
  if(X[1] == 3.5)
    return 1;
  if(X[2] == 3.5)
    return 2;
  if(X[3] == 3.5)
    return 3;
  if(X[4] == 3.5)
    return 4;

The implementation of the "select" template could be rather similar to "for_each".

namespace boost {
namespace mpl {

namespace aux {

template <bool done = true>
struct select_impl
{
    template<
          typename Iterator
        , typename LastIterator
        , typename TransformFunc
        , typename F
        >
    static bool execute(
          Iterator*
        , LastIterator*
        , TransformFunc*
        , F
        )
    {
        return false;
    }
};

template <>
struct select_impl<false>
{
    template<
          typename Iterator
        , typename LastIterator
        , typename TransformFunc
        , typename F
        >
    static bool execute(
          Iterator*
        , LastIterator*
        , TransformFunc* 
        , F f
        )
    {
        typedef typename Iterator::type item;
        typedef typename apply1<TransformFunc,item>::type arg;
    
        value_initialized<arg> x;
        if(aux::unwrap(f, 0)(boost::get(x)))
            return true;
        
        typedef typename Iterator::next iter;
        return select_impl<boost::is_same<iter,LastIterator>::value>::execute(
            (iter*)0, (LastIterator*)0, (TransformFunc*)0, f);
    }
};

} // namespace aux

template<
      typename Sequence
    , typename TransformOp
    , typename F
    >
inline
bool select(F f, Sequence* = 0, TransformOp* = 0)
{
    typedef typename begin<Sequence>::type first;
    typedef typename end<Sequence>::type last;
    typedef typename lambda<TransformOp>::type transform_op;

    return aux::select_impl< boost::is_same<first,last>::value >::execute(
        (first*)0, (last*)0, (transform_op*)0, f);
}

template<
      typename Sequence
    , typename F
    >
inline
bool select(F f, Sequence* = 0)
{
    return select<Sequence, identity<> >(f);
}

} // namespace mpl
} // namespace boost

 
        



Regards,
                                

        Jonathan Wang
        [EMAIL PROTECTED]
          2003-02-13


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to