[vc10, rvalue references] Поломали, однако
От: byleas  
Дата: 20.10.09 20:43
Оценка:
Сабж.

Такой код уже не катит:
  // <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);
  }
c++0x
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.