Re: [Boost-bugs] [Boost C++ Libraries] #9449: Boost.MPL min_element bug for equal elements (fix included)

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #9449: Boost.MPL min_element bug for equal elements (fix included)
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2013-12-02 11:27:48


#9449: Boost.MPL min_element bug for equal elements (fix included)
--------------------------------------------+------------------------------
  Reporter: Rein Halbersma <rhalbersma@…> | Owner: agurtovoy
      Type: Bugs | Status: new
 Milestone: To Be Determined | Component: mpl
   Version: Boost 1.55.0 | Severity: Problem
Resolution: | Keywords: min_element, bug
--------------------------------------------+------------------------------

Comment (by Rein Halbersma <rhalbersma@…>):

 Sorry, the bug report contained bad code: `lambda<Predicate, _2, _1>` (not
 sure why this even compiled since lambda only takes 2 arguments). The (now
 hopefully) correct fix should be to write `bind<typename
 lambda<Predicate>::type, _2, _1>` instead.

 Because `max_element` takes a lambda expression (metafunction class or
 placeholder expression), and because `bind` takes only a metafunction
 class, we need `lambda<Predicate>::type` to convert a placeholder
 expression `Predicate` into a metafunction class.

 Corresponding modified test program at: http://coliru.stacked-
 crooked.com/a/f8658230325c9dd8

 {{{#!c++
 #include <boost/mpl/begin_end.hpp>
 #include <boost/mpl/bind.hpp>
 #include <boost/mpl/distance.hpp>
 #include <boost/mpl/lambda.hpp>
 #include <boost/mpl/less_equal.hpp>
 #include <boost/mpl/max_element.hpp>
 #include <boost/mpl/min_element.hpp>
 #include <boost/mpl/placeholders.hpp>
 #include <boost/mpl/vector_c.hpp>
 #include <iostream>

 using namespace boost::mpl;

 template<class Sequence, class Predicate = less<_1, _2>>
 struct stable_min_element
 :
     // mpl::min_element uses max_element<Sequence, not_<Predicate>>
     // max_element takes a lambda expression (metafunction class or
 placeholder expression)
     // bind takes only a metafunction class, so we need
 lambda<Predicate>::type
     // to convert a placeholder expression Predicate into a metafunction
 class
     max_element<Sequence, bind<typename lambda<Predicate>::type, _2, _1>>
 {};

 int main()
 {
     using V = vector_c<int, 1, 1, 1>;

     using MinIdx = distance<begin<V>::type, min_element<V>::type>;
     using LEMinIdx = distance<begin<V>::type, min_element<V,
 less_equal<_1, _2> >::type>;
     using SMinIdx = distance<begin<V>::type,
 stable_min_element<V>::type>;
     using MaxIdx = distance<begin<V>::type, max_element<V>::type>;

     std::cout << MinIdx::value; // ERROR: prints 2 instead of 0
     std::cout << LEMinIdx::value; // 0
     std::cout << SMinIdx::value; // 0
     std::cout << MaxIdx::value; // 0
 }
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/9449#comment:1>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:14 UTC