Boost logo

Boost Users :

From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2007-03-18 09:55:09


Scott Meyers wrote:
> It will take me a few days to digest your comments

Hopefully not because they're confusing :-). I tried to increase
conciseness with my second post.

> (this is largely new
> territory for me), but I wanted to acknowledge your help now. Thanks
> very much.

Thanks too -- a reader who's new to the territory is most valuable to
improve one's communication skills.

>> The problem comes down to that MPL can't know where one placeholder
>> expression starts and where another one ends (denoted by uppercase
>> identifiers, above):
>
> Yes, I ran into this problem playing around as a result of the help
> posted earlier. As I said, it will take me a while to get a grasp on
> what you've done. I have to look a lot of stuff up and write a lot of
> test cases :-)

There's a slightly altered approach to this problem attached to this
message for some additional fun.

Regards,
Tobias


#include <boost/type_traits/is_same.hpp>

#include <boost/mpl/not.hpp>
#include <boost/mpl/end.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/bind.hpp>
#include <boost/mpl/lambda.hpp>

#include <boost/mpl/apply.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/assert.hpp>

namespace mpl = boost::mpl;
using namespace mpl::placeholders;
using boost::is_same;

// contains_if

template<typename Seq, typename Pred>
struct contains_if
  : mpl::not_< boost::is_same<typename mpl::find_if<Seq,Pred>::type,
        typename mpl::end<Seq>::type> >
{ };

// test it
typedef mpl::vector<int> v1;
BOOST_MPL_ASSERT(( contains_if<v1,is_same<_,int> > ));
BOOST_MPL_ASSERT_NOT(( contains_if<v1,is_same<_,char> > ));

// contains implemented on top of it
//
// other than mpl::contains this version takes a binary predicate to parametrize
// comparison

template<typename S, typename T, typename Compare = boost::is_same<_1,_2> >
struct contains
// uses 'lambda', because 'bind' requires a Metafunction Class instead of an
// arbitrary Lambda Expressions
  : contains_if< S, mpl::bind<typename mpl::lambda<Compare>::type,T,_1> >
{ };

// test it
BOOST_MPL_ASSERT(( ::contains<v1,int> ));
BOOST_MPL_ASSERT_NOT(( ::contains<v1,char> ));

// a facility that allows to sustain the evaluation of placeholder expressions

template<typename PlaceholderExpr>
struct defer
{
    template<typename IgnoredPlaceholder> struct get
    {
        typedef PlaceholderExpr type;
    };

    // return a dummy placeholder expression that evaluates to the
    // original one (without substitution applied)
    typedef typename defer<PlaceholderExpr>::template get<_> type;
};

// test it
BOOST_MPL_ASSERT(( is_same<mpl::apply< defer<_1>::type ,int>::type, _1> ));
BOOST_MPL_ASSERT(( is_same<mpl::apply<mpl::apply< defer<_1>::type,
    int>::type,int>::type, int> ));

// now implement includes on top of

template<typename SuperSeq, typename SubSeq,
    typename Pred = boost::is_same<_1,_2> >
struct includes
  : mpl::not_< contains_if< SubSeq, mpl::not_< contains<SuperSeq,_1,
      typename defer<Pred>::type > > > >
{ };

// test it
typedef mpl::vector<int> v1;
typedef mpl::vector<int,char> v2;
BOOST_MPL_ASSERT(( includes<v2, v1> ));
BOOST_MPL_ASSERT_NOT(( includes<v1, v2> ));


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net