|
Boost : |
From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2001-12-18 06:45:08
Peter Dimov wrote:
> I think that a compile-time port of boost.bind would be a
> valuable addition to MPL.
Peter, this is totally cool! The absence of full-fledged compile-time bind
was the only thing that my expression templates implementation lacked, and I
am so glad you did it! (now I can throw my own half-working version ;). In
fact, bind implements 90% of the compile-time lambda facility, and the rest
10% is below:
template<typename T>
struct expr_templ
{
typedef T type;
};
template<
template<typename> class UnaryFunction
, typename T
>
struct expr_templ< UnaryFunction<T> >
{
typedef typename bind<
boost::mpl::make_f_x<UnaryFunction>
, typename expr_templ<T>::type
>::type type;
};
template<
template<typename, typename> class BinaryFunction
, typename T1
, typename T2
>
struct expr_templ< BinaryFunction<T1,T2> >
{
typedef typename bind<
boost::mpl::make_f_xy<BinaryFunction>
, typename expr_templ<T1>::type
, typename expr_templ<T2>::type
>::type type;
};
// more specializations for ternary function template, etc.
That's all! Given the above, one can, for example, write:
template<typename T>
struct size_of
{
BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(T));
typedef boost::mpl::integral_c<std::size_t,value> type;
};
typedef expr_templ<
mpl::logical_and<
mpl::logical_not< mpl::logical_or< is_same<_1,int>,
is_same<long, _1> > >
, mpl::greater< size_of<_1>, mpl::int_c<8> >
>
>::type f1;
BOOST_STATIC_ASSERT((!f1::apply<int>::type::value));
BOOST_STATIC_ASSERT((!f1::apply<long>::type::value));
BOOST_STATIC_ASSERT((f1::apply<my>::type::value));
or
typedef expr_templ<
mpl::logical_or<
mpl::logical_or< is_same<_1,_2>, is_same<_1,my> >
, is_same<_1,_3>
>
>::type f2;
BOOST_STATIC_ASSERT((f2::apply<int,int,void>::type::value));
BOOST_STATIC_ASSERT((!f2::apply<long,int,void>::type::value));
BOOST_STATIC_ASSERT((f2::apply<void,my,void>::type::value));
BOOST_STATIC_ASSERT((f2::apply<my,int,void>::type::value));
etc.
Modifying the algorithms to apply such "parsing" internally, so they can
accept ordinary function classes as well as expression templates is a matter
of minutes..
The only caveat here is that 'is_same' class template is not exactly
'boost::is_same':
template<typename T1, typename T2>
struct is_same
{
BOOST_STATIC_CONSTANT(bool, value = false);
typedef boost::mpl::bool_t<value> type; // '::type' interface is
"must have"
};
template<typename T>
struct is_same<T,T>
{
BOOST_STATIC_CONSTANT(bool, value = true);
typedef boost::mpl::bool_t<value> type;
};
A lot of type traits class templates do not provide the '::type' interface
if they "return" boolean value, and this is a show stopper for the bind
library.
Oh, and _1, _2, etc. should be complete types - consider, for example
size_of<_1> ;). Well, actually this is a part of much bigger issue...
Aleksey
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk