Сабж.
Такой код уже не катит:
// <utility>
template <class T>
struct identity
{
typedef T type;
const T& operator()(const T& x) const { return x; }
};
template <class T>
inline
T&& forward(typename identity<T>::type&& t)
{
return t;
}
struct X{};
void g(X&& gx);
void f(X&& fx)
{
g(fx); // can't convert from 'X' to 'X&&' (You cannot bind an lvalue to an rvalue reference) (1)
g(std::forward<X>(fx); // аналогично. нонсенс! (2)
X x;
X&& rvx1 = x; // error (3)
X&& rvx2 = X(); // ok (4)
}
Вроде бы с++0х были какие-то
предложения по изменениям, но в основном это было связано с работой perfect forwarding. А вот чтоб так брутально..
gcc 4.5 считает, что здесь всё ок. Скорее всего (точно не помню сейчас), в первом вызове "g(fx)" фактически получим lvalue reference параметром. Но почему это стало ошибкой?
Примеры из блога vc10 также поломались.
Вообще, с forward<> понятно, ситуация описана в N2951, где сравниваются 6 (!) реализаций. Последняя самая зубодробительная, приведена ниже.
Неясен лишь запрет
неявного преобразования lvalue в rvalue (3).
// предложенная реализация forward<>
template <class T, class U>
inline T&& forward(U&& u,
typename enable_if<
(is_lvalue_reference<T>::value ? is_lvalue_reference<U>::value : true) &&
is_convertible<typename remove_reference<U>::type*, typename remove_reference<T>::type*>::value,
void>::type* =0)
{
return static_cast<T&&>(u);
}