Сравнение std:: minmax с парой
Стандартные алгоритмы min
и max
можно сравнить с одним значением. Однако возвращаемое значение алгоритма minmax
не может сравниваться с парой значений:
#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
}
Пример Live
Причина в том, что make_pair(2, 1)
возвращает a pair<int, int>
и minmax(1, 2)
возвращает a pair<const int&, const int&>
. Для pair
нет перегрузок референциального смешивания operator==
.
Затем исправление должно явно писать std::pair<const int&, const int&>(int, int)
или обернуть это в домашней функции make_cref_pair
.
Вопросы: существует ли более чистый способ сравнения возвращаемого значения minmax
с pair
значений? И правильно ли я обрабатывал ссылки в моем make_cref_pair
?
Ответы
Ответ 1
std::minmax
имеет перегрузку initializer_list
. Это возвращает пару non-const
non-reference:
static_assert(std::minmax({2, 1}) == std::make_pair(1, 2));
К сожалению, это может быть менее результативным, так как сложности соответственно являются "точно одним сравнением" и "не более (3/2) * t.size()
приложений соответствующего предиката".
Ответ 2
Одна вещь, которую вы можете сделать, это воспользоваться перегрузкой std::minmax
, которая принимает std::initializer_list<T>
и возвращает std::pair<T,T>
. Используя это, вы могли бы
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));
}
Какой будет компилировать и позволит вам избавиться от make_cref_pair
. Он вызывает std::minmax_element
, поэтому я не уверен, что это снижает эффективность или нет.
Ответ 3
Один из вариантов состоит в том, чтобы явно преобразовать левую сторону в 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));
}