Home Reading Searching Subscribe Sponsors Statistics Posting Contact Spam Lists Links About Hosting Filtering Features Download Marketing Archives FAQ Blog From: Eric Niebler boost-consulting.com> Subject: [interest?] min, max and more ... solved! Newsgroups: gmane.comp.lib.boost.devel Date: Monday 10th July 2006 17:24:29 UTC (over 11 years ago) ```<< Background ... >> Way back in 1995, Scott Meyers issued a challenge to the C++ community to build a better min/max utility [1]. In 2003, Andrei took up the challenge [2], but his results were unsatisfactory for reasons both technical and aesthetic [3]. In 2005, I wrote about some tricks you can do with the conditional operator [4]. Andrei suggested a way the tricks could be used to finally resolve Scott's min/max challenge. Still, the nagging lvalue/rvalue problems remained. (Consider that for some user-defined type A, this: "A const &a = std::min(A(1),A(2));" causes the reference to "a" to dangle.) << The Present ... >> Last week, at Scott's prodding, I took the issue up again and finally resolved the lvalue/rvalue problem. The result is a macro MAX(a,b) that behaves *exactly* like ((a)<(b)?(b):(a)), except that it does not reevaluate its arguments. It has the following advantages over std::max: 1) It supports both const and non-const arguments (including mixing the two in a single call). 2) It supports arguments of different types. 3) The expression type of MAX(a,b) is naturally identical to "((a)<(b)?(b):(a))", relying on the compiler's type promotion rules. 4) The rvalue/lvalue-ness of MAX(a,b) is identical to "((a)<(b)?(b):(a))", making it possible to use it on the left side of an assignment, for instance: "MAX(a,b) = 1". This also means that dangling references are impossible. The code is 100% C++98 compliant, and should work on gcc and comeau. (msvc will need some work-arounds.) The code is below. << The Future ... >> Is there interest in turning this into a BOOST_MIN/BOOST_MAX library? << The Code >> #include #include #include #include #include template boost::type* encode_type(Type &) { return 0; } template boost::type* encode_type(Type const &) { return 0; } /////////////////////////////////////////////////////////////////////////////// // max_impl template struct max_impl { max_impl(Left &left, Right &right) : left_(left) , right_(right) {} struct private_type_ {}; // can't ever return an array or an abstract type by value typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< boost::mpl::or_, boost::is_array > , private_type_ , Ret >::type value_type; operator value_type() { return this->left_ < this->right_ ? this->right_ : this->left_; } operator Ret &() const { return this->left_ < this->right_ ? this->right_ : this->left_; } private: Left &left_; Right &right_; }; /////////////////////////////////////////////////////////////////////////////// // max_fun template max_impl max_fun(Left &left, Right &right, boost::type *) { return max_impl(left, right); } template max_impl max_fun(Left const &left, Right &right, boost::type *) { return max_impl(left, right); } template max_impl max_fun(Left &left, Right const &right, boost::type *) { return max_impl(left, right); } template max_impl max_fun(Left const &left, Right const &right, boost::type *) { return max_impl(left, right); } #define MAX(a,b)\ (true\ ? max_fun((a), (b), \ (true? 0 : encode_type(true? (a) : (b))))\ : (true? (a) : (b))) [1] http://www.aristeia.com/Papers/C++ReportColumns/jan95.pdf [2] http://www.ddj.com/dept/cpp/184403774 [3] Andrei's solution ignores lvalue/rvalue issues as raised in Francis Glassborow's c++std-lib-15426, and it depends on Loki, requiring a large amount of template code that largely duplicates the type promotion logic already present in the compiler. [4] http://www.artima.com/cppsource/foreach.html -- Eric Niebler Boost Consulting www.boost-consulting.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost```
CD: 4ms