Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: Eric Niebler <eric <at> 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: 3ms