func(int&&) vs std::move
От: rain.drop  
Дата: 18.11.18 18:41
Оценка: 6 (1) :)
void func(int&&) noexcept {
}

int main() {
   int x = 10;
   func(x); // error: cannot bind 'int' lvalue to 'int&&' 
}


// template< class T >
// typename std::remove_reference<T>::type&& move( T&& t ) noexcept;
int main() {
   int x = 10;
   std::move(x); // OK
}


Почему std::move принимает x, а func нет?
Re: func(int&&) vs std::move
От: Шахтер Интернет  
Дата: 18.11.18 18:47
Оценка:
Здравствуйте, rain.drop, Вы писали:


RD>
RD>void func(int&&) noexcept {
RD>}

RD>int main() {
RD>   int x = 10;
RD>   func(x); // error: cannot bind 'int' lvalue to 'int&&' 
RD>}
RD>


RD>
RD>// template< class T >
RD>// typename std::remove_reference<T>::type&& move( T&& t ) noexcept;
RD>int main() {
RD>   int x = 10;
RD>   std::move(x); // OK
RD>}
RD>


RD>Почему std::move принимает x, а func нет?


Компилятор чётко объясняет, почему.

// error: cannot bind 'int' lvalue to 'int&&'


Если хочешь вызвать func с lvalue, используй std::move :

func(std::move(x));
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: func(int&&) vs std::move
От: rain.drop  
Дата: 18.11.18 18:51
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Компилятор чётко объясняет, почему.


Ш>

Ш>// error: cannot bind 'int' lvalue to 'int&&'


Так а std::move(x) тогда почему эту же ошибку не выдает?
Re: func(int&&) vs std::move
От: Пирожочек  
Дата: 18.11.18 18:53
Оценка: +1 -1
Здравствуйте, rain.drop, Вы писали:

RD>Почему std::move принимает x, а func нет?


std::move это, по сути, и не функция вообще, а просто каст T& к T&&
Re[3]: func(int&&) vs std::move
От: andyp  
Дата: 18.11.18 19:07
Оценка: 2 (1) +1 :)
Здравствуйте, rain.drop, Вы писали:

RD>Так а std::move(x) тогда почему эту же ошибку не выдает?



Потому что в

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

выделенное является т.н. forwarding reference, а не тем, что ты думаешь
Re: func(int&&) vs std::move
От: rg45 СССР  
Дата: 18.11.18 19:09
Оценка: 27 (3) +1
Здравствуйте, rain.drop, Вы писали:

RD>Почему std::move принимает x, а func нет?


Объяви func шаблонной, как move, она тоже начнет принимать все, что угодно:

template <typename T>
void func(T&&) noexcept {}


Потому, что в шаблонном варианте мы имеем дело не с rvalue reference, пусть тебя не обманывает внешняя похожесть, а с особым видом ссылок, называемых forwarding references. Которые способны забиндить на себя вообще все, что угодно, в виду их всеядности.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 18.11.2018 19:11 rg45 . Предыдущая версия . Еще …
Отредактировано 18.11.2018 19:10 rg45 . Предыдущая версия .
Re: func(int&&) vs std::move
От: lpd Черногория  
Дата: 18.11.18 19:28
Оценка: -11
Здравствуйте, rain.drop, Вы писали:

RD>Почему std::move ...?


Еще один изучает C++14 . std::move интересен только некоторым C++-фрикам, практической пользы же никакой в язык не приносит. Если тебе нужны 3% скорости, управляй памятью вручную, учи ассемблер, и не страдай из-за выдумок фанатиков из C++ комитета.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[2]: func(int&&) vs std::move
От: AlexGin Беларусь  
Дата: 19.11.18 10:38
Оценка: +1
Здравствуйте, lpd, Вы писали:

lpd>Здравствуйте, rain.drop, Вы писали:


RD>>Почему std::move ...?


lpd>Еще один изучает C++14 . std::move интересен только некоторым C++-фрикам, практической пользы же никакой в язык не приносит.


Позвольте НЕ согласиться. Практическая польза — в виде экономии памяти (переносим, вместо того, чтобы копировать) — налицо.

lpd>Если тебе нужны 3% скорости, управляй памятью вручную, учи ассемблер, и не страдай из-за выдумок фанатиков из C++ комитета.


Это требования жизни и развития языка C++ в наше время. То, что Вы предлагаете — это вариант скорее для embedded приложений, нежели для общепринятого C++ мейнстрима.
Ну и вариант, когда только один волшебник разработчик может понять проект, к чему неминуемо приведёт предлагаемый Вами подход, — это путь в никуда
Re[3]: func(int&&) vs std::move
От: lpd Черногория  
Дата: 19.11.18 11:45
Оценка: :)
Здравствуйте, AlexGin, Вы писали:

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


lpd>>Здравствуйте, rain.drop, Вы писали:


RD>>>Почему std::move ...?


lpd>>Еще один изучает C++14 . std::move интересен только некоторым C++-фрикам, практической пользы же никакой в язык не приносит.

AG>
AG>Позвольте НЕ согласиться. Практическая польза — в виде экономии памяти (переносим, вместо того, чтобы копировать) — налицо.

Дело вообще не в памяти, а в экономии времени на копировании. Только люди на Java/C# пишут код, который в 3 раза медленнее, поэтому вдвойне глупо расставлять rvalue-reference и std::move, особенно если алгоритм неоптимален, или оптимизируемый код вообще не является узким местом. Не говоря уже о мизерном выигрыше в общем быстродействии, деленном на усложнении кода, являющимися результатом использования этих фич. C++14 можно рассматривать как хобби, хотя мне и непонятное, но не не нужно тащить его в каждый проект, особенно если программисты не знают гораздо более важных вещей.

AG>Это требования жизни и развития языка C++ в наше время.

Стадный инстинкт как он есть.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Отредактировано 19.11.2018 11:46 lpd . Предыдущая версия .
Re[4]: func(int&&) vs std::move
От: andyp  
Дата: 19.11.18 20:39
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>Дело вообще не в памяти, а в экономии времени на копировании. Только люди на Java/C# пишут код, который в 3 раза медленнее, поэтому вдвойне глупо расставлять rvalue-reference и std::move, особенно если алгоритм неоптимален, или оптимизируемый код вообще не является узким местом. Не говоря уже о мизерном выигрыше в общем быстродействии, деленном на усложнении кода, являющимися результатом использования этих фич. C++14 можно рассматривать как хобби, хотя мне и непонятное, но не не нужно тащить его в каждый проект, особенно если программисты не знают гораздо более важных вещей.


Дело вообще не в оптимизации, а в том, что перемещение как концепция должно быть явно выражено средствами языка. Концепция перемещения существует вне зависимости от того, находишь ты ее лишней или нет. Как 0 в математике. О том, что он есть, тоже не сразу догадались. Например, есть алгоритмы, где пустая ячейка путешествует по массиву, как дырка в полупроводнике. Язык без перемещений не позволяет явно выразить такую семантику. Да даже простейший swap — это по сути ни разу не копирования, а именно перемещения — ты ж просто меняешь вещи местами. Когда в жизни барахло перемещаешь, тоже создаешь же какие-то копии?

lpd>Стадный инстинкт как он есть.

. Многие вещи нам непонятны не потому, что наши понятия слабы; но потому, что сии вещи не входят в круг наших понятий(с). А ты свой взгляд через амбразуру тут безапелляционно выдаешь за пример высшей мудрости.
Re[2]: func(int&&) vs std::move
От: T4r4sB Россия  
Дата: 19.11.18 20:56
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, rain.drop, Вы писали:



Ш>Если хочешь вызвать func с lvalue, используй std::move :


Внимание вопрос — можно ли это сделать, не подключая СТЛ?
Re[3]: func(int&&) vs std::move
От: andyp  
Дата: 19.11.18 21:15
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Внимание вопрос — можно ли это сделать, не подключая СТЛ?


Можно. static_cast-ом шарахнуть по конкретному объекту, про который ты знаешь, что он точно lvalue. В принципе и свой move достаточно просто завелосипедить, только еще придется и remove_reference написать, что тоже несложно. Кроме remove_reference и static_cast внутри и нет ничего.

Вот куски из msvc stl



    // TEMPLATE CLASS remove_reference
template<class _Ty>
    struct remove_reference
    {    // remove reference
    typedef _Ty type;
    };

template<class _Ty>
    struct remove_reference<_Ty&>
    {    // remove reference
    typedef _Ty type;
    };

template<class _Ty>
    struct remove_reference<_Ty&&>
    {    // remove rvalue reference
    typedef _Ty type;
    };


        // TEMPLATE FUNCTION move
template<class _Ty> inline
    constexpr typename remove_reference<_Ty>::type&&
        move(_Ty&& _Arg) _NOEXCEPT
    {    // forward _Arg as movable
    return (static_cast<typename remove_reference<_Ty>::type&&>(_Arg));
    }
Re[3]: func(int&&) vs std::move
От: rg45 СССР  
Дата: 19.11.18 21:29
Оценка:
Здравствуйте, T4r4sB, Вы писали:

Ш>>Если хочешь вызвать func с lvalue, используй std::move :


TB>Внимание вопрос — можно ли это сделать, не подключая СТЛ?


Ну, коль скоро требования к функции move известны, более того зафиксированы в стандарте, я не вижу препятствий тому, чтоб реализовать эту функцию, или ее аналог, самостоятельно.

23.2.5 Forward/move helpers

template <class T> constexpr remove_reference_t<T>&& move(T&& t) noexcept;
5 Returns: static_cast<remove_reference_t<T>&&>(t).

--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: func(int&&) vs std::move
От: Masterspline  
Дата: 20.11.18 03:09
Оценка:
TB>Внимание вопрос — можно ли это сделать, не подключая СТЛ?

Если что-то есть в STL, а точнее в стандартной библиотеке, которая идет с компилятором, то лучше не изобретать велосипед, а использовать стандартную библиотеку. Кроме того, что написанное в std гораздо лучше протестировано, там иногда используют интринсики компилятора, которые работают быстрее, чем если использовать только возможности языка, описанные в стандарте (SFINAE или рекурсивного инстанциирования шаблонов, например).
Re[5]: func(int&&) vs std::move
От: lpd Черногория  
Дата: 20.11.18 07:05
Оценка: +1
Здравствуйте, andyp, Вы писали:

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


lpd>>Дело вообще не в памяти, а в экономии времени на копировании.


A>Дело вообще не в оптимизации, а в том, что перемещение как концепция должно быть явно выражено средствами языка.


Я в принципе согласен, что перемещение переменных — идея интересная для разработчиков высокоуровнего языка. Но C++ раньше был не сборником интересных теоретических фич. Появись перемещение в каком-нибудь другом языке, не было бы ажиотажа, и большинство не изучало бы тонкости преобразований rvalue-ссылок. "Но раз это в Стандарте C++, то необходимо использовать перемещение как можно чаще, иначе код несовременный." — рассуждают все, от студентов до кадровичек.
Объективно же в тех крайне редких случаях, когда есть смысл оптимизировать копирование какой-нибудь переменной, можно просто напрямую скопировать указатель на данные, по сути сделав то же самое, но без введения новых типов данных в язык.
И точно программисту, знающему C++98, полезнее изучить ассемблер, скрипты, Linux, устройство ОС, алгоритмы, чем вникать в тонкости rvalue-reference.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[6]: func(int&&) vs std::move
От: andyp  
Дата: 20.11.18 09:43
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>Я в принципе согласен, что перемещение переменных — идея интересная для разработчиков высокоуровнего языка. Но C++ раньше был не сборником интересных теоретических фич. Появись перемещение в каком-нибудь другом языке, не было бы ажиотажа, и большинство не изучало бы тонкости преобразований rvalue-ссылок. "Но раз это в Стандарте C++, то необходимо использовать перемещение как можно чаще, иначе код несовременный." — рассуждают все, от студентов до кадровичек.

lpd>Объективно же в тех крайне редких случаях, когда есть смысл оптимизировать копирование какой-нибудь переменной, можно просто напрямую скопировать указатель на данные, по сути сделав то же самое, но без введения новых типов данных в язык.

Да уж. Залёты "практиков" как на ладони в дизайне auto_ptr. Пока понятия были слабы, нормальных смартпоинтеров мы не имели. Если любопытно, найди в интернете про дизайн функций max и min. Тоже очень познавательно.

lpd>И точно программисту, знающему C++98, полезнее изучить ассемблер, скрипты, Linux, устройство ОС, алгоритмы, чем вникать в тонкости rvalue-reference.


У каждого свой C++.
Re[3]: func(int&&) vs std::move
От: Erop Россия  
Дата: 20.11.18 11:29
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>Ну и вариант, когда только один волшебник разработчик может понять проект, к чему неминуемо приведёт предлагаемый Вами подход, — это путь в никуда



Неконтролируемое применение семантики перемещения позволяет запутать код намного продвинутее, чем ассемблер
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: func(int&&) vs std::move
От: night beast СССР  
Дата: 20.11.18 11:31
Оценка:
Здравствуйте, Erop, Вы писали:

E>Неконтролируемое применение семантики перемещения позволяет запутать код намного продвинутее, чем ассемблер


есть реальные примеры?
Re[7]: func(int&&) vs std::move
От: Erop Россия  
Дата: 20.11.18 11:35
Оценка:
Здравствуйте, andyp, Вы писали:

A>Да уж. Залёты "практиков" как на ладони в дизайне auto_ptr. Пока понятия были слабы, нормальных смартпоинтеров мы не имели.


Уж не знаю, кто такие "вы", но я нормальными интрузивными смарт-поинтами пользуюсь года с 1995 где-то...
Ну и вообще COM_ptr уже о-о-о-о-о-о-чень давно придумали. Задолго до STL и стандарта 1998-го года
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: func(int&&) vs std::move
От: andyp  
Дата: 20.11.18 11:58
Оценка:
Здравствуйте, Erop, Вы писали:

E>Уж не знаю, кто такие "вы", но я нормальными интрузивными смарт-поинтами пользуюсь года с 1995 где-то...

E>Ну и вообще COM_ptr уже о-о-о-о-о-о-чень давно придумали. Задолго до STL и стандарта 1998-го года

Ну так auto_ptr тоже вполне себе можно было пользоваться, если забыть, что его копирование таковым не является, но в то же время оно все-таки есть .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.