Re[20]: to uzhas
От: Evgeny.Panasyuk Россия  
Дата: 14.03.13 17:47
Оценка:
Здравствуйте, rg45, Вы писали:

R>>>Табличка, красивая, жаль только, она слабо коррелирует и со стандартом и с практикой:

EP>>Всё в порядке:
EP>>
  Скрытый текст
EP>>#include <utility>

EP>>struct A
EP>>{
EP>>   A() { }
EP>>   A(A&&) { }
   
EP>>   A(const A&) = delete;
EP>>   A& operator=(const A&) = delete;
EP>>};

EP>>template<typename T>
EP>>void forwarding(T &&t)
EP>>{
EP>>   A(std::forward<T>(t));
EP>>}

EP>>int main()
EP>>{
EP>>   A first;
EP>>   //forwarding(std::move(first));
EP>>   forwarding(first);
EP>>}
EP>>

EP>>

EP>>Compilation finished with errors:
EP>>source.cpp: In instantiation of 'void forwarding(T&&) [b]with T = A&[/b]]':
EP>>source.cpp:22:20: required from here
EP>>source.cpp:15:4: error: use of deleted function 'A::A(const A&)'
EP>>source.cpp:8:4: error: declared here



R>http://liveworkspace.org/code/OImmo$5

R>Ну где ж в порядке-то?

Я выше показал(обрати внимание, на какой строчке "use of deleted function"), что forward не всегда возвращает rvref — табличка работает.
Если ты считаешь, что какой-то из пунктов таблички не работает — покажи пример, с указанием того, что именно ты считаешь не работает.
Re[16]: to uzhas
От: Evgeny.Panasyuk Россия  
Дата: 14.03.13 18:10
Оценка: 18 (1)
Здравствуйте, rg45, Вы писали:

R>Ну, во-первых, то, о чем я уже говорил — несоответствующее название. Во-вторых, нечеткость семантики — по обеим функциям в стандарте говорится только о том, как они реализованы, а их семантика и область применимости остается на додумывание пользователю.


Семантика следует из определения, "20.2.3 forward/move helpers" — там даже примеры есть.

R>То, что во многих случаях эти функции взаимозаменяемы еще больше путает.


Функции используются в разных контекстах, у них разная семантика, разный синтаксис.

R>Вы скажете, есть дополнительные материалы, в которой все подробно расписано? Отлично! Объясните, пожалуйста, со ссылкой на эти материалы, почему успешно компилируются следующие примеры:


Ок, слайды с презентации Майерса, номер 28 "Reference Collapsing"

R>http://liveworkspace.org/code/1ykoSY$1


std::forward<A>(first)

выбирается
template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;

T == A, return type is T&& -> (A)&& -> A&& (rvalue reference)
далее — A(A&&)

R>http://liveworkspace.org/code/OImmo$5


forwarding(std::forward<A>(first));

выбирается
template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;

T == A, return type is T&& -> (A)&& -> A&& (rvalue reference),
далее
template<typename T>
void forwarding(T &&t)
{
   A(std::forward<T>(t));
}

T == A
выбирается
template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;

(потому, что named rvalue reference)
T == A, return type is T&& -> (A)&& -> A&& (rvalue reference)
далее — A(A&&)
Re[17]: to uzhas
От: rg45 СССР  
Дата: 14.03.13 18:51
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:
...

Теперь я вижу, что не разобрался в вопросе, буду разбираться. Спасибо за объяснение и ссылки.
--
Справедливость выше закона. А человечность выше справедливости.
Re[17]: to uzhas
От: Evgeny.Panasyuk Россия  
Дата: 14.03.13 18:59
Оценка:
Чтобы увидеть reference collapsing в действии, нужно рассмотреть пример где std::forward возвращает lvalue reference:

forwarding(first);

->
template<typename T>
void forwarding(T &&t)
{
   A(std::forward<T>(t));
}

T == A&. Это правило есть на 26 слайде Майерса(что также видно из ошибки "source.cpp: In instantiation of 'void forwarding(T&&) [ with T = A& ]'"):
void forwarding((A&) &&t)
{
   A(std::forward<(A&)>(t));
}

Reference Collapsing ->
void forwarding(A &t)
{
   A(std::forward<A&>(t));
}

Выбирается
template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;

T == A& ->
(A&)&& forward(typename remove_reference<(A&)>::type& t) noexcept;

Reference Collapsing и применение remove_reference ->
A& forward(A& t) noexcept;

return type is A&
Re[18]: to uzhas
От: rg45 СССР  
Дата: 14.03.13 19:16
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Чтобы увидеть reference collapsing в действии, нужно рассмотреть пример где std::forward возвращает lvalue reference:


Да, теперь все стало понятно. В стандарте хоть и не используется термин "universal reference", тем не менее он здесь описан достаточно ясно:

8.3.2/6
If a typedef (7.1.3), a type template-parameter (14.3.1), or a decltype-specifier (7.1.6.2) denotes a type TR
that is a reference to a type T, an attempt to create the type “lvalue reference to cv TR” creates the type
“lvalue reference to T”, while an attempt to create the type “rvalue reference to cv TR” creates the type TR.
[ Example:

int i;
typedef int& LRI;
typedef int&& RRI;
LRI& r1 = i; // r1 has the type int&
const LRI& r2 = i; // r2 has the type int&
const LRI&& r3 = i; // r3 has the type int&
RRI& r4 = i; // r4 has the type int&
RRI&& r5 = 5; // r5 has the type int&&
decltype(r2)& r6 = i; // r6 has the type int&
decltype(r2)&& r7 = i; // r7 has the type int&

—end example ]

Для меня это просто открытие
--
Справедливость выше закона. А человечность выше справедливости.
Re[19]: to uzhas
От: Evgeny.Panasyuk Россия  
Дата: 14.03.13 19:32
Оценка:
Здравствуйте, rg45, Вы писали:

R>Да, теперь все стало понятно. В стандарте хоть и не используется термин "universal reference", тем не менее он здесь описан достаточно ясно:

R>

R>8.3.2/6


Это скорее просто Reference Collapsing Rules example.
То, что Майерс называет "universal reference", относится к && в контексте type deduction, например:
auto &&v = ...;
or
template<typename T>
void f(T &&v);

То есть для "universal reference" наличие type deduction — обязательно.

R>Для меня это просто открытие


Ну так ждём-с TC++PL 4th edition
Re[20]: to uzhas
От: rg45 СССР  
Дата: 15.03.13 10:26
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

R>>Для меня это просто открытие


EP>Ну так ждём-с TC++PL 4th edition


Да уж, без предварительной подготовки подобный use case вводит в состояние легкого шока:

http://ideone.com/EbsODp

#include <iostream>

template<typename T>
T foo(T&& t)
{
  return t;   
}

int main()
{
   int a = 0;
   foo(a) = 42;
   std::cout << a << std::endl; // Output: 42
}
--
Справедливость выше закона. А человечность выше справедливости.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.