специализация для rvalue ссылок
От: sergii.p  
Дата: 21.08.20 14:07
Оценка:
всем привет. Что-то совсем запутался.

#include <iostream>
#include <vector>
using namespace std;

template<typename Collection>
std::enable_if_t<
    !std::is_rvalue_reference_v<Collection>,
    void
>
operator|(const Collection& col, int)
{
    cout<<"lvalue\n";
}

template<typename Collection>
std::enable_if_t<
    std::is_rvalue_reference_v<Collection>,
    void
>
operator|(Collection&& col, int)
{
    cout<<"rvalue\n";
}

int main()
{
    std::vector<int> v;
    v | 1;
    std::move(v) | 1;
    return 0;
}


выдаёт

lvalue                                                                                                                                        
lvalue


а хочу чтобы выводило
lvalue                                                                                                                                        
rvalue


Как сия магия записывается?
https://www.onlinegdb.com/SySG486fP
Re: специализация для rvalue ссылок
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.08.20 14:16
Оценка:

T&& Doesn’t Always Mean “Rvalue Reference”


https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: специализация для rvalue ссылок
От: AeroSun  
Дата: 21.08.20 15:00
Оценка:
Здравствуйте, niXman, Вы писали:


X>

X>T&& Doesn’t Always Mean “Rvalue Reference”


X>https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers


С одной стороны на практике оказалось, что мув и не нужен в большинстве случаев.
Но с другой стороны....интересно, ему самому не кажется это говнокодом?
Когда нужно учитывать/держать в голове неявные вещи чуть ли не на каждом шагу — это же 100% признак говнокода/говноархитектуры.
Re: специализация для rvalue ссылок
От: B0FEE664  
Дата: 21.08.20 15:39
Оценка: 2 (1)
Здравствуйте, sergii.p, Вы писали:

SP>Как сия магия записывается?

SP>https://www.onlinegdb.com/SySG486fP
так: https://www.onlinegdb.com/fork/SySG486fP

template<typename Collection>
std::enable_if_t<
    !std::is_rvalue_reference_v<Collection&>,
    void
>
operator|(const Collection& col, int)
{
    cout<<"lvalue\n";
}

template<typename Collection>
std::enable_if_t<
    std::is_rvalue_reference_v<Collection&&>,
    void
>
operator|(Collection&& col, int)
{
    cout<<"rvalue\n";
}
И каждый день — без права на ошибку...
Re[2]: специализация для rvalue ссылок
От: sergii.p  
Дата: 21.08.20 17:22
Оценка:
Здравствуйте, niXman, Вы писали:


X>

X>T&& Doesn’t Always Mean “Rvalue Reference”


X>https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers


если бы вы внимательно читали, то обнаружили бы, что вопрос больше о sfinae чем о rvalue ссылках. Я там мог везде поставить const&
Re[2]: специализация для rvalue ссылок
От: sergii.p  
Дата: 21.08.20 17:36
Оценка:
Здравствуйте, B0FEE664, Вы писали:

оно конечно работает. Но теперь я ничего не понимаю Почему условия разные? Они получается не покрывают 100% случаев?
Re[2]: специализация для rvalue ссылок
От: rg45 СССР  
Дата: 21.08.20 18:34
Оценка:
Здравствуйте, B0FEE664, Вы писали:

В принципе, все верно, только в перdой перегрузке std::is_rvalue_reference_v<Collection&> всегда будет вычисляться в false (с логическим отрицанием соответственно всегда будет true), поэтому SFINAE здесь просто не дает никакого эффекта и можно упростить до:


template<typename Collection>
void operator|(const Collection& col, int)
{
    cout<<"lvalue\n";
}

template<typename Collection>
std::enable_if_t<std::is_rvalue_reference_v<Collection&&>>
operator|(Collection&& col, int)
{
    cout<<"rvalue\n";
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 22.08.2020 7:00 rg45 . Предыдущая версия . Еще …
Отредактировано 21.08.2020 19:24 rg45 . Предыдущая версия .
Re[3]: специализация для rvalue ссылок
От: rg45 СССР  
Дата: 21.08.20 18:44
Оценка:
Здравствуйте, sergii.p, Вы писали:

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


SP>оно конечно работает. Но теперь я ничего не понимаю Почему условия разные? Они получается не покрывают 100% случаев?


Тут фокус в том, что, поскольку Collection — шаблонный параметр, Collection&& — это особый вид ссылки, называемый forwarding reference. Эти ссылки "всеядны" в том смысле, что могут сопоставляться не только с rvalue ссылками, но и с lvalue. Благодаря своей всеядности функции с такими ссылками в параметрах способны выигрывать подстановку там, где это не ожидается. Для того, чтобы вторая прегрузка использовалась только для rvalue выкфжений, подстановку lvalue выражений нужно блокировать при помощи SFINAE, как показал B0FEE664.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 21.08.2020 19:07 rg45 . Предыдущая версия . Еще …
Отредактировано 21.08.2020 18:49 rg45 . Предыдущая версия .
Отредактировано 21.08.2020 18:45 rg45 . Предыдущая версия .
Re[3]: специализация для rvalue ссылок
От: rg45 СССР  
Дата: 22.08.20 18:31
Оценка: 2 (1)
Здравствуйте, sergii.p, Вы писали:

SP>оно конечно работает. Но теперь я ничего не понимаю Почему условия разные? Они получается не покрывают 100% случаев?


Я подправил твой пример, чтоб работало так, как ты хочешь. Это не самый рациональный способ, зато он поможет тебе быстрее понять, как работают forwarding references.

http://coliru.stacked-crooked.com/a/4da3e07d486bab4c

#include <iostream>
#include <vector>

template<typename Collection>
std::enable_if_t<std::is_lvalue_reference_v<Collection>>
operator|(Collection&& col, int)
{
    std::cout<<"lvalue\n";
}

template<typename Collection>
std::enable_if_t<!std::is_lvalue_reference_v<Collection>>
operator|(Collection&& col, int)
{
    std::cout<<"rvalue\n";
}

int main()
{
    std::vector<int> v;
    v | 1;
    std::move(v) | 1;
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: специализация для rvalue ссылок
От: _NN_ www.nemerleweb.com
Дата: 23.08.20 06:58
Оценка: 2 (1)
Здравствуйте, sergii.p, Вы писали:

Если нужно rvalue следует добавить const:



https://www.walletfox.com/course/cheatsheets_cpp.php
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: специализация для rvalue ссылок
От: rg45 СССР  
Дата: 23.08.20 08:29
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Если нужно rvalue следует добавить const:


После чего модификация объекта становится недоступной. В то время как главной мотивацией для появления rvalue ссылок было как раз то, что далеко не всегда rvalue автоматом означает константность.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: специализация для rvalue ссылок
От: _NN_ www.nemerleweb.com
Дата: 23.08.20 08:35
Оценка:
Здравствуйте, rg45, Вы писали:

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


_NN>>Если нужно rvalue следует добавить const:


R>После чего модификация объекта становится недоступной. В то время как главной мотивацией для появления rvalue ссылок было как раз то, что далеко не всегда rvalue автоматом означает константность.


Ну тут надо исходить из задачи.
В данном выше примере изменений объекта не было.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: специализация для rvalue ссылок
От: rg45 СССР  
Дата: 23.08.20 08:45
Оценка: +2
Здравствуйте, _NN_, Вы писали:

_NN>Ну тут надо исходить из задачи.

_NN>В данном выше примере изменений объекта не было.

Для данного случая это подходит. Но я все же хотел обратить внимание, что это решение не является всеобщим.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: специализация для rvalue ссылок
От: B0FEE664  
Дата: 23.08.20 11:42
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>оно конечно работает. Но теперь я ничего не понимаю Почему условия разные? Они получается не покрывают 100% случаев?


Мы пытаемся сделать перегрузку функций по типу аргумента col.
Тип аргумента функции записывается слева от имени аргумента, поэтому:
operator|(const Collection& col, int) ===> 'const Collection&'
operator|(Collection&& col, int)      ===> 'Collection&&'

поэтому в enable_if следует анализировать именно эти типы (которые я указал в апострофах), а не Collection. Тут следует подметить, что в коде выше по ветке я упустил const — это, вообще говоря, ошибка, но она ничего не меняет.
Так же в условиях enable_if тип аргумента можно заменить на эквивалентный, поэтому для примера rg45
Автор: rg45
Дата: 22.08.20
:
std::is_lvalue_reference_v<Collection&&> == std::is_lvalue_reference_v<Collection>

— это своего рода "оптимизация", которая может усложнить чтение кода.
И каждый день — без права на ошибку...
Re[4]: специализация для rvalue ссылок
От: sergii.p  
Дата: 25.08.20 07:50
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>В данном выше примере изменений объекта не было.


пример упрощённый. Конечно дальше нужно перемещать объект.
Хотя может лучше впилить один const_cast, чем городить enable_if-ы. Уж точно читабельнее.
Re[5]: специализация для rvalue ссылок
От: sergii.p  
Дата: 25.08.20 08:03
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>пример упрощённый. Конечно дальше нужно перемещать объект.

SP>Хотя может лучше впилить один const_cast, чем городить enable_if-ы. Уж точно читабельнее.

стоп, туплю. Может же перемещаться константный объект, так что const_cast отпадает
Отредактировано 25.08.2020 8:03 sergii.p . Предыдущая версия .
Re[6]: специализация для rvalue ссылок
От: rg45 СССР  
Дата: 25.08.20 08:24
Оценка: +1
Здравствуйте, sergii.p, Вы писали:

SP>стоп, туплю. Может же перемещаться константный объект, так что const_cast отпадает


Перемещение может менять состояние исходного объекта, что противоречит константности. Move constructor принимает неконстантную rvalue ссылку, иначе, это не move конструктор. В стандартной библиотеке и бусте, все константные объекты только копируются. Хотя, написать можно что угодно, конечно.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 25.08.2020 8:58 rg45 . Предыдущая версия .
Re[7]: специализация для rvalue ссылок
От: σ  
Дата: 25.08.20 09:25
Оценка: 12 (1)
R>Move constructor принимает неконстантную rvalue ссылку, иначе, это не move конструктор.

Твоя же ссылка первой же строкой это опровергает.
Re[8]: специализация для rvalue ссылок
От: rg45 СССР  
Дата: 25.08.20 09:30
Оценка:
Здравствуйте, σ, Вы писали:

σ>Твоя же ссылка первой же строкой это опровергает.


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