Re[7]: to uzhas
От: rg45 СССР  
Дата: 14.03.13 13:46
Оценка:
Здравствуйте, rg45, Вы писали:

EP>>А как же алгоритмы, например быстрый rotate?

EP>>А как же C++11 std::swap в конце концов?
EP>>
EP>>template <class T> void swap (T& a, T& b)
EP>>{
EP>>  T c(std::move(a)); a=std::move(b); b=std::move(c);
EP>>}
EP>>



R>swap можно можно реализовать при помощи std::forward:


R>http://liveworkspace.org/code/3Mun0g$7


R>
R>template <class T> 
R>void swap (T& a, T& b)
R>{
R>  T c(std::forward<T>(a)); a=std::forward<T>(b); b=std::forward<T>(c);
R>}
R>



to uzhas:
---------
Я действительно не понимаю, что мешает мне в данном случае использовать std::forward вместо std::move. Я полагаю, если ты выражаешь свое несогласие в виде оценки, то, вероятно, можешь выразить его и на словах? Буду благодарен если объяснишь.
--
Справедливость выше закона. А человечность выше справедливости.
Re[7]: std::unique_ptr. Передача владения.
От: Evgeny.Panasyuk Россия  
Дата: 14.03.13 13:46
Оценка:
Здравствуйте, rg45, Вы писали:

R>>>Возможно, я ошибаюсь, но у меня такая предубежденность, что при идеальных архитектуре и дизайне move не нужен вовсе. Т.о. move — это просто костыль, частота использования которого может служить мерилом плохого дизайна.

EP>>А как же алгоритмы, например быстрый rotate?
EP>>А как же C++11 std::swap в конце концов?
R>swap можно можно реализовать при помощи std::forward:

std::forward предназначен для других целей, и очевидно что в этом случае у std::move синтаксис лучше
move можно реализовать при помощи раскидывания static_cast по всему коду — а смысл?
Я правильно тебя понимаю, что "move — это просто костыль, буду использовать что угодно, хоть forward, хоть static_cast, но только не его"?
Re[8]: std::unique_ptr. Передача владения.
От: rg45 СССР  
Дата: 14.03.13 13:59
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

R>>>>Возможно, я ошибаюсь, но у меня такая предубежденность, что при идеальных архитектуре и дизайне move не нужен вовсе. Т.о. move — это просто костыль, частота использования которого может служить мерилом плохого дизайна.

EP>>>А как же алгоритмы, например быстрый rotate?
EP>>>А как же C++11 std::swap в конце концов?
R>>swap можно можно реализовать при помощи std::forward:

EP>std::forward предназначен для других целей, и очевидно что в этом случае у std::move синтаксис лучше


Я в курсе, для чего это предназначалось. Да только кривовато это как-то получилось: функция называется move, хотя на самом деле ничего не перемещает. Я ожидал более весомой аргументации, чем "они хотели как лучше...".

EP>move можно реализовать при помощи раскидывания static_cast по всему коду — а смысл?

EP>Я правильно тебя понимаю, что "move — это просто костыль, буду использовать что угодно, хоть forward, хоть static_cast, но только не его"?

Грубо говоря, да. Хотя бы потому, что и forward, и static_cast приводят меня ровно к тому же результату (rvalue ссылка), при этом они не скрывают от меня сути происходящего за не уместным в данном случае словом 'move'.
--
Справедливость выше закона. А человечность выше справедливости.
Re[8]: to uzhas
От: uzhas Ниоткуда  
Дата: 14.03.13 14:15
Оценка:
Здравствуйте, rg45, Вы писали:

R>Я действительно не понимаю, что мешает мне в данном случае использовать std::forward вместо std::move.


оно просто не работает, как если бы это был std::move, потому что именно благодаря std::move можно переместить значение из c в b
внутри std::swap обязательно нужно использовать rvalue ref, а std::forward просто прокидывает входящий тип и для того, чтобы он правильно его прокидывал нужно принимать T&&. для функции с двумя типами T он будет давать осечки
std::move для меня на пальцах — это автоматизация swap, то есть встроенная в язык фишка для обмена двух переменных (swap) и эта фишка ортогональна качеству дизайна имхо

что такое std:;forward можно почитать здесь:
http://thbecker.net/articles/rvalue_references/section_01.html
http://stackoverflow.com/questions/3106110/what-are-move-semantics
Re[9]: std::unique_ptr. Передача владения.
От: Evgeny.Panasyuk Россия  
Дата: 14.03.13 14:18
Оценка:
Здравствуйте, rg45, Вы писали:

EP>>move можно реализовать при помощи раскидывания static_cast по всему коду — а смысл?

EP>>Я правильно тебя понимаю, что "move — это просто костыль, буду использовать что угодно, хоть forward, хоть static_cast, но только не его"?
R>Грубо говоря, да. Хотя бы потому, что и forward, и static_cast приводят меня ровно к тому же результату (rvalue ссылка), при этом они не скрывают от меня сути происходящего за не уместным в данном случае словом 'move'.

Допустим есть код:
f(std::move(obj));
// Что здесь можно сказать об obj ?

1. obj должен быть destructable
2. если это стандартный тип (либо тип придерживающийся тех же правил), то он:

Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

Это такое же "valid but unspecified state", как и при Basic Exception Safety Guarantee.

Допустим, внутри f это:
void f(Obj &&obj)
{
    // do nothing
}

Пункты 1 и 2 выполняются и в этом случае.
Re[9]: to uzhas
От: rg45 СССР  
Дата: 14.03.13 14:26
Оценка: -1
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, rg45, Вы писали:


R>>Я действительно не понимаю, что мешает мне в данном случае использовать std::forward вместо std::move.


U>оно просто не работает, как если бы это был std::move, потому что именно благодаря std::move можно переместить значение из c в b

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

Я тоже приведу кое-какие ссылки — на стандарт C++11:

20.2.3 forward/move helpers

template <class T> typename remove_reference<T>::type&& move(T&& t) noexcept;

Returns: static_cast<typename remove_reference<T>::type&&>(t).


std::move ничего никуда не перемещает!

И еще раз приведу, пример из моего предыдущего сообщения, а также ссылку на работающий пример:

http://liveworkspace.org/code/3Mun0g$7

template <class T> 
void swap (T& a, T& b)
{
  T c(std::forward<T>(a)); a=std::forward<T>(b); b=std::forward<T>(c);
}


Что конкретно в нем не так, и какие осечки в нем происходят?
--
Справедливость выше закона. А человечность выше справедливости.
Re[10]: to uzhas
От: uzhas Ниоткуда  
Дата: 14.03.13 14:38
Оценка: 18 (1)
Здравствуйте, rg45, Вы писали:

R>std::move ничего никуда не перемещает!

я не спорю с этим, возможно, плохо выразился. std::move "создает" rvaluе ref и соответствующие конструкторы типа T уже сделают перемещение
std::forward сможет сделать rvalue ref только при определенных обстоятельствах

R>Что конкретно в нем не так

слишком много копирований
Re[9]: swap move forward
От: Evgeny.Panasyuk Россия  
Дата: 14.03.13 14:41
Оценка: +1
Здравствуйте, uzhas, Вы писали:

U>внутри std::swap обязательно нужно использовать rvalue ref, а std::forward просто прокидывает входящий тип и для того, чтобы он правильно его прокидывал нужно принимать T&&.


В случае rg45 нет "прокидки", и если использовать его swap с type deduction, то там будет rvref.
Но, в примере со swap, разница с обычным move хоть формальная, но есть.
Например, если не использовать type deduction (сферический пример):
#include <iostream>
#include <ostream>
#include <utility>

template<typename T,int> void type_is();

template <int i,class T> 
void swap (T& a, T& b)
{
  type_is<decltype(std::forward<T>(a)),2*i+1>();
  type_is<decltype(std::move(a)),2*i+2>();
  T c(std::forward<T>(a)); a=std::forward<T>(b); b=std::forward<T>(c);
}

int main() 
{
   int a = 1, b = 2;
   swap<0>(a, b);
   swap<1,int&>(a, b);
   std::cout << a << ", " << b << std::endl;
}

Вывод:

Compilation finished with errors:
/tmp/cci7QIMZ.o: In function `main':
source.cpp: ( .text.startup+0x5 ) : undefined reference to `void type_is<int&&, 1>()'
source.cpp: ( .text.startup+0xa ) : undefined reference to `void type_is<int&&, 2>()'
source.cpp: ( .text.startup+0xf ) : undefined reference to `void type_is<int&, 3>()'
source.cpp: ( .text.startup+0x14 ) : undefined reference to `void type_is<int&&, 4>()'
collect2: error: ld returned 1 exit status

Re[11]: to uzhas
От: rg45 СССР  
Дата: 14.03.13 14:55
Оценка:
Здравствуйте, uzhas, Вы писали:

R>>Что конкретно в нем не так

U>слишком много копирований

Так-так, это уже интересно. Опыт это подтверждает:

http://liveworkspace.org/code/3Mun0g$13.

Я, правда, пока еще не понял, откуда они берутся (с учетом того, что std::forward возвращет rvalue reference), буду разбираться, но все равно спасибо.
--
Справедливость выше закона. А человечность выше справедливости.
Re[10]: swap move forward
От: uzhas Ниоткуда  
Дата: 14.03.13 14:58
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>В случае rg45 нет "прокидки", и если использовать его swap с type deduction, то там будет rvref.


точно, я был невнимателен
в этом случае мне непринципиально std::forward или std::move использовать. лишь бы перемещалось
Re[12]: to uzhas
От: Evgeny.Panasyuk Россия  
Дата: 14.03.13 14:59
Оценка: 18 (1)
Здравствуйте, rg45, Вы писали:

R>>>Что конкретно в нем не так

U>>слишком много копирований
R>Так-так, это уже интересно. Опыт это подтверждает:
R>http://liveworkspace.org/code/3Mun0g$13.
R>Я, правда, пока еще не понял, откуда они берутся (с учетом того, что std::forward возвращет rvalue reference), буду разбираться, но все равно спасибо.

Нужен move assignment:

A &operator=(A&&)
...
a=std::forward<T>(b);
Re[11]: swap move forward
От: uzhas Ниоткуда  
Дата: 14.03.13 15:02
Оценка:
Здравствуйте, uzhas, Вы писали:

U>в этом случае мне непринципиально std::forward или std::move использовать. лишь бы перемещалось


на самом деле они работают по-разному, нужен именно std::move
хватит меня запутывать!
Re[13]: to uzhas
От: rg45 СССР  
Дата: 14.03.13 15:04
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

R>>>>Что конкретно в нем не так

U>>>слишком много копирований
R>>Так-так, это уже интересно. Опыт это подтверждает:
R>>http://liveworkspace.org/code/3Mun0g$13.
R>>Я, правда, пока еще не понял, откуда они берутся (с учетом того, что std::forward возвращет rvalue reference), буду разбираться, но все равно спасибо.

EP>Нужен move assignment:


EP>
EP>A &operator=(A&&)
EP>...
EP>a=std::forward<T>(b);
EP>


Да, точно! Спасибо.

Тогда заходим на второй круг (нафиг нам этот move)
--
Справедливость выше закона. А человечность выше справедливости.
Re[14]: to uzhas
От: Evgeny.Panasyuk Россия  
Дата: 14.03.13 15:09
Оценка:
Здравствуйте, rg45, Вы писали:

R>Тогда заходим на второй круг (нафиг нам этот move)


Если сравнивать с "forward как move", то
1. move всегда возвращает rvref
2. move использует type-deduction, ему не нужно явно передавать тип
Re[11]: to uzhas
От: rg45 СССР  
Дата: 14.03.13 15:09
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, rg45, Вы писали:


R>>std::move ничего никуда не перемещает!

U>я не спорю с этим, возможно, плохо выразился. std::move "создает" rvaluе ref и соответствующие конструкторы типа T уже сделают перемещение
U>std::forward сможет сделать rvalue ref только при определенных обстоятельствах

R>>Что конкретно в нем не так

U>слишком много копирований

Итак, продолжаем разговор. Копирований здесь нет вовсе: http://liveworkspace.org/code/4oRZSF$0.

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

EP>Если сравнивать с "forward как move", то

EP>1. move всегда возвращает rvref

std::forward тоже всегда возвращает rvref:

20.2.3/2

template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;
template <class T> T&& forward(typename remove_reference<T>::type&& t) noexcept;

2 Returns: static_cast<T&&>(t).


EP>2. move использует type-deduction, ему не нужно явно передавать тип


Ну это уже проблема второго порядка. Она и так-то не очень критична, кроме того может быть тривиально решена как на уровне пользователя, так и на уровне стандарта. То, что std::forward не сбивает с толку неподходящим названием, ИМХО, гораздо важнее.
--
Справедливость выше закона. А человечность выше справедливости.
Re[12]: to uzhas
От: rg45 СССР  
Дата: 14.03.13 15:18
Оценка:
R>Здравствуйте, uzhas, Вы писали:

R>>>Что конкретно в нем не так

U>>слишком много копирований

R>Итак, продолжаем разговор. Копирований здесь нет вовсе: http://liveworkspace.org/code/4oRZSF$0.

R>Есть что возразить?

Вот так даже еще интересней:

http://liveworkspace.org/code/4oRZSF$1
--
Справедливость выше закона. А человечность выше справедливости.
Re[16]: to uzhas
От: uzhas Ниоткуда  
Дата: 14.03.13 15:19
Оценка:
Здравствуйте, rg45, Вы писали:

R>std::forward тоже всегда возвращает rvref:


по ссылкам, что я ранее уже дал можно найти следующее

C++11, by contrast, introduces the following reference collapsing rules:
A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&

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

EP>>Если сравнивать с "forward как move", то

EP>>1. move всегда возвращает rvref

R>std::forward тоже всегда возвращает rvref:

R>

R>20.2.3/2
R>

R>template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;
R>template <class T> T&& forward(typename remove_reference<T>::type&& t) noexcept;
R>

R>2 Returns: static_cast<T&&>(t).


Нет, не всегда:
#include <utility>

template<typename T> void type_is();

int main()
{
   int a;
   type_is<decltype(std::forward<int>(a))>();
   type_is<decltype(std::forward<int&>(a))>();
}

Compilation finished with errors:
/tmp/cceig6tw.o: In function `main':
source.cpp: (.text.startup+0x5): undefined reference to `void type_is<int&&>()'
source.cpp: (.text.startup+0xa): undefined reference to `void type_is<int&>()'
collect2: error: ld returned 1 exit status

У Майерса целый talk на эту тему: C++ and Beyond 2012: Scott Meyers &mdash; Universal References in C++11.
Re[12]: to uzhas
От: uzhas Ниоткуда  
Дата: 14.03.13 15:24
Оценка:
Здравствуйте, rg45, Вы писали:

R>Есть что возразить?


я не понимаю что ты хочешь доказать?
тебе не нравится только название std::move? или сама возможность перетаскивать объекты?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.