
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> ));