|
Boost : |
From: Jonathan Wang (babysloth_at_[hidden])
Date: 2003-02-13 05:10:54
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
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡babysloth_at_[hidden]
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡2003-02-13
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk