Reputation: 70526
The standard algorithms min
and max
can be compared against a single value. However, the minmax
algorithm return value cannot be compared against a pair of values:
#include <algorithm>
#include <utility>
template<class T1, class T2>
constexpr auto make_cref_pair(T1&& t1, T2&& t2)
{
return std::pair<T1 const&, T2 const&>(std::forward<T1>(t1), std::forward<T2>(t2));
}
int main()
{
static_assert(std::min(2, 1) == 1); // OK
static_assert(std::max(2, 1) == 2); // OK
//static_assert(std::minmax(2, 1) == std::make_pair(1, 2)); // ERROR, const int& vs int pair comparison
static_assert(std::minmax(2, 1) == std::pair<const int&, const int&>(1, 2)); // OK
static_assert(std::minmax(2, 1) == make_cref_pair(1, 2)); // OK
}
The reason is that make_pair(2, 1)
returns a pair<int, int>
and minmax(1, 2)
returns a pair<const int&, const int&>
. There are no referenceness-mixing operator==
overloads for pair
.
The fix is then to explicitly write std::pair<const int&, const int&>(int, int)
or to wrap this in a home-made make_cref_pair
function.
Questions: is there a cleaner way to compare the minmax
return value against a pair
of values? And did I correctly handle the references in my make_cref_pair
?
Upvotes: 11
Views: 900
Reputation: 5668
One option is to explicitly convert the left-hand side to std::pair<int,int>
:
#include <algorithm>
#include <utility>
template <typename T1, typename T2>
constexpr std::pair<T1,T2> myminmax(const T1& t1, const T2& t2)
{
return std::minmax(t1,t2);
}
int main()
{
static_assert(myminmax(2, 1) == std::make_pair(1, 2));
}
Upvotes: 3
Reputation: 180720
One thing you could do is take advantage of the std::minmax
overload that takes a std::initializer_list<T>
and returns a std::pair<T,T>
. Using that you could have
int main()
{
const int a = 10, b = 20;
static_assert(std::minmax({2, 1}) == std::make_pair(1, 2));
static_assert(std::minmax({a, b}) == std::make_pair(a, b));
}
Which will compile and allows you to get rid of make_cref_pair
. It does call std::minmax_element
so I am not sure if this decreases the efficiency or not.
Upvotes: 5
Reputation: 136
std::minmax
has an initializer_list
overload. This returns a non-const
non-reference pair:
static_assert(std::minmax({2, 1}) == std::make_pair(1, 2));
Unfortunately this may be less performant, since the complexities respectively are "exactly one comparison" and "at most (3/2) * t.size()
applications of the corresponding predicate".
Upvotes: 12