Минимальный алгоритм обычно выражается как это:
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);
}
Мне кажется, вы пытаетесь упростить проблему. К сожалению, получить его полностью правильно - задача нетривиальная. Если вы не читали N2199 , сейчас было бы хорошее время для этого. Ссылки на Rvalue продолжают развиваться, поэтому его эталонная реализация min и max, вероятно, больше не совсем правильная, но, по крайней мере, она должна быть довольно приличной отправной точкой. Предупреждение: эталонная реализация намного сложнее, чем вам может понравиться!
Вам не нужна идеальная пересылка, здесь вы хотите вернуть либо 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