минута и идеальная передача

Минимальный алгоритм обычно выражается как это:

template <typename T>
const T& min(const T& x, const T& y)
{
    return y < x ? y : x;
}

Однако это не позволяет конструкции формы min(a, b) = 0. Можно достигнуть этого с дополнительной перегрузкой:

template <typename T>
T& min(T& x, T& y)
{
    return y < x ? y : x;
}

То, что я хотел бы сделать, объединяют эти две перегрузки через идеальную передачу:

template <typename T>
T&& min(T&& x, T&& y)
{
    return y < x ? std::forward<T>(y) : std::forward<T>(x);
}

Однако g ++ 4.5.0 выкладывает предупреждение для min(2, 4) то, что я возвращаю ссылку на временный файл. Я делал что-то не так?


Хорошо, я получаю его. Проблема с условным оператором. В моем первом решении, если я звоню min(2, 4) условный оператор видит xvalue и таким образом перемещается от переданного x произвести временный объект. Конечно, было бы опасно возвратить это ссылкой! Если я передаю целое выражение вместо x и y отдельно, компилятор больше не жалуется:

template <typename T>
T&& min(T&& x, T&& y)
{
    return std::forward<T>(y < x ? y : x);
}

Хорошо, я избавился от ссылок для арифметических типов :)

#include <type_traits>

template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, T>::type
min(T x, T y)
{
    return y < x ? y : x;
}

template <typename T>
typename std::enable_if<!std::is_arithmetic<T>::value, T&&>::type
min(T&& x, T&& y)
{
    return std::forward<T>(y < x ? y : x);
}
7
задан fredoverflow 24 June 2010 в 15:11
поделиться

2 ответа

Мне кажется, вы пытаетесь упростить проблему. К сожалению, получить его полностью правильно - задача нетривиальная. Если вы не читали N2199 , сейчас было бы хорошее время для этого. Ссылки на Rvalue продолжают развиваться, поэтому его эталонная реализация min и max, вероятно, больше не совсем правильная, но, по крайней мере, она должна быть довольно приличной отправной точкой. Предупреждение: эталонная реализация намного сложнее, чем вам может понравиться!

3
ответ дан 7 December 2019 в 14:29
поделиться

Вам не нужна идеальная пересылка, здесь вы хотите вернуть либо T & , либо const T & и никогда T && . std :: forward предназначен для передачи одного из ваших параметров другой функции, а не для возвращаемых значений.

Я думаю, что вам нужно:

template <typename T>
min(T&& x, T&& y) -> decltype(x)
{
    return y < x ? y : x;
}

ИЗМЕНИТЬ, чтобы избежать проблемы с висячими ссылками:

template <typename T>
struct dedangle { typedef T type; }

template <typename T>
struct dedangle<const T&> { typedef T type; }

template <typename T, typename U>
min(T&& x, U&& y) -> dedangle<decltype(0?y:x)>::type
{
    return y < x ? y : x;
}

// dedangle is re-usable by max, etc, so its cost is amortized
1
ответ дан 7 December 2019 в 14:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: