
On 05/21/13 18:04, Larry Evans wrote:
On 05/21/13 15:43, Louis Dionne wrote:
Hi,
Some higher order algorithms in the MPL have a default for the lambda expression they accept. A good example is `boost::mpl::equal`:
template <typename S1, typename S2, typename Pred = is_same<_, _> > struct equal;
This works fine most of the time, but I was recently bitten by the following:
template <typename VectorOfVectors, typename Vector> struct find_vector : find_if< VectorOfVectors, equal<Vector, _1> > { };
typedef find_vector< vector< vector<int, int>, vector<char, char> >, vector<char, char> >::type ThisWillBreak;
What happens here is that the `equal<Vector, _1>` expression inside `find_vector` really is `equal<Vector, _1, is_same<_1, _2> >` because of the default value for the predicate to `equal`. When the lambda is evaluated, the placholders inside the inner `is_same<_1, _2>` expression are replaced too, which yields unexpected results.
Using
template <typename S1, typename S2, typename Pred = typename lambda<is_same<_, _> >::type> struct equal;
or equivalently
template <typename S1, typename S2, typename Pred = quote2<is_same> > struct equal;
fixes the issue. Also note that all of the unit tests of the MPL still pass with these changes. Is the current behavior intended, or should I submit a patch?
Regards,
Louis Dionne
This sounds like a problem similar to the one here:
http://article.gmane.org/gmane.comp.lib.boost.devel/227344
Maybe reading that thread would give you some ideas for a solution.
OOPS. I should have read further and noted your solution using lambda. Sorry for noise. However, with the attached and your changes and gcc4.8 I'm getting errors: bug_with_default_lambda.cpp:18:12: required from 'struct find_vector<boost::mpl::vector<boost::mpl::vector<int, int>, boost::mpl::vector<char, char> >, boost::mpl::vector<char, char> >' bug_with_default_lambda.cpp:30:6: required from here /home/evansl/prog_dev/boost-svn/ro/boost_1_53_0/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:36:8: error: no class template named 'apply' in 'struct boost::mpl::equal<boost::mpl::vector<char, char>, mpl_::arg<1>, boost::mpl::protect<boost::mpl::bind2<boost::mpl::quote2<boost::is_same, mpl_::void_>, mpl_::arg<-1>, mpl_::arg<-1> >, 0> >' struct apply_wrap1 ^ In file included from /home/evansl/prog_dev/boost-svn/ro/boost_1_53_0/boost/mpl/not.hpp:19:0, from /home/evansl/prog_dev/boost-svn/ro/boost_1_53_0/boost/mpl/assert.hpp:17, from /home/evansl/prog_dev/boost-svn/ro/boost_1_53_0/boost/mpl/aux_/na_assert.hpp:23, from /home/evansl/prog_dev/boost-svn/ro/boost_1_53_0/boost/mpl/arg.hpp:25, from /home/evansl/prog_dev/boost-svn/ro/boost_1_53_0/boost/mpl/placeholders.hpp:24, from /home/evansl/prog_dev/boost-svn/ro/boost_1_53_0/boost/mpl/apply.hpp:24, from /home/evansl/prog_dev/boost-svn/ro/boost_1_53_0/boost/mpl/aux_/iter_fold_if_impl.hpp:22, from /home/evansl/prog_dev/boost-svn/ro/boost_1_53_0/boost/mpl/equal.hpp:17, from bug_with_default_lambda.cpp:10: . . . The mpl/equal.hpp contains your suggested modification: template< typename BOOST_MPL_AUX_NA_PARAM(Sequence1) , typename BOOST_MPL_AUX_NA_PARAM(Sequence2) #ifdef LJE_USE_LAMBDA_PREDICATE_IS_SAME , typename Predicate = typename lambda<is_same<_,_> >::type #else , typename Predicate = is_same<_,_> #endif > struct equal : aux::msvc_eti_base< typename aux::equal_impl<Sequence1,Sequence2,Predicate>::type >::type { BOOST_MPL_AUX_LAMBDA_SUPPORT(2,equal,(Sequence1,Sequence2)) }; Could you supply a complete test case so I can see what I might be doing wrong to reproduce your solution? TIA. -regards, Larry