Adam Hunyadi Adam Hunyadi - 1 month ago 6
C++ Question

Is there a way to easily handle functions returning std::pairs?

C++11 has function

std::minmax_element
which returns a pair of values. This, however, is quite confusing to handle and read, and produces an extra, later useless variable to pollute the scope.

auto lhsMinmax = std::minmax_element(lhs.begin(), lhs.end());
int &lhsMin = *(lhsMinMax.first);
int &lhsMax = *(lhsMinmax.second);


Is there a better way to do this? Something like:

int lhsMin;
int lhsMax;
std::make_pair<int&, int&>(lhsMin, lhsMax).swap(
std::minmax_element(lhs.begin(), lhs.end()));

Answer

This looks like enough of a common case to prompt a helper function:

template <class T, std::size_t...Idx>
auto deref_impl(T &&tuple, std::index_sequence<Idx...>) {
    return std::tuple<decltype(*std::get<Idx>(std::forward<T>(tuple)))...>(*std::get<Idx>(std::forward<T>(tuple))...);
}

template <class T>
auto deref(T &&tuple)
    -> decltype(deref_impl(std::forward<T>(tuple), std::make_index_sequence<std::tuple_size<std::remove_reference_t<T>>::value>{})) {
    return deref_impl(std::forward<T>(tuple), std::make_index_sequence<std::tuple_size<std::remove_reference_t<T>>::value>{});
}

// ...

int lhsMin;
int lhsMax;
std::tie(lhsMin,lhsMax) = deref(std::minmax_element(lhs.begin(), lhs.end()));

index_sequence is C++14, but a full implementation can be made in C++11.

Note: I'd keep the repeated decltype in deref's return type even in C++14, so that SFINAE can apply.

See it live on Coliru