Russian Qt Forum
Апрель 26, 2024, 20:34 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3 4   Вниз
  Печать  
Автор Тема: rvalue и operator ->  (Прочитано 22116 раз)
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« : Ноябрь 22, 2018, 10:54 »

Привет всем!

Имеется возможность реализовывать методы конкретно для rvalue и lvalue значений, например,

Код
C++ (Qt)
struct My
{
   void method () && {}
   void method () & {}
};
 

таким образом закладывать для rvalue экземпляров типа My более эффективную реализацию, или даже предусматривать разный api

Код
C++ (Qt)
struct My
{
   void rvalueMethod () && {}
   void lvalueMethod () & {}
};
 

Однако использование поверх типа My любого указателя (или обертки) с доступом к членам через оператор -> не позволяет вызвать rvalue методы.
Например, для указателей std

Код
C++ (Qt)
::std::make_shared< My >()->lvalueMethod(); // OK
::std::make_shared< My >()->rvalueMethod(); // Error
 

На просторах интернета нашел только http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3723.html

Можно ли вообще реализовать вызов rvalue метода посредством оператора -> ?
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #1 : Ноябрь 22, 2018, 12:19 »

Если решать "в лоб", то как-то так получается:
Код
C++ (Qt)
#include <memory>
#include <iostream>
 
using namespace std;
 
struct A
{
   void lvalueMethod() &
   { cout << "lvalueMethod" << endl; }
 
   void rvalueMethod() &&
   { cout << "rvalueMethod" << endl; }
};
 
int main()
{
   make_shared<A>()->lvalueMethod();
   move(*make_shared<A>().operator->()).rvalueMethod();
 
   return 0;
}

А так может надо мутить с переопределением operator->(), чтобы возвращалась lvalue или rvalue в зависимости от того, применяется этот оператор к lvalue или rvalue. Но это в своих классах так можно, от стандартных, типа shared_ptr такого вряд ли дождёшься.
Записан

Пока сам не сделаешь...
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #2 : Ноябрь 22, 2018, 16:52 »

Достаточно очевидно, что у _шаред_ птра не может быть рвалуе оператора. Надо объяснять почему?
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #3 : Ноябрь 22, 2018, 17:22 »

Достаточно очевидно, что у _шаред_ птра не может быть рвалуе оператора. Надо объяснять почему?

Так и знал, что конкретно на shared_ptr обратят внимание  Смеющийся Смеющийся Смеющийся
Он здесь так сбоку, просто для примера.

А если я такой специфический класс-обертку хочу реализовать?

Код
C++ (Qt)
template < typename _Value >
class Wraper
{
   _Value m_value;
public:
   _Value * operator -> () & { return &m_value; }
   // ??? operator -> () && { return ???; }
};
 

Но чтобы работало так

Код
C++ (Qt)
   Wraper< My >()->rvalueMethod();
 

Возможно такое реализовать в принципе?
Или ждать возможного внедрения предложения в стандарт N3723 (ссылка вначале) или предложений для оператора "точка" (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4477.pdf , http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0352r1.pdf?
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #4 : Ноябрь 22, 2018, 17:34 »

А так может надо мутить с переопределением operator->(), чтобы возвращалась lvalue или rvalue в зависимости от того, применяется этот оператор к lvalue или rvalue. Но это в своих классах так можно, от стандартных, типа shared_ptr такого вряд ли дождёшься.

Так вот, что бы такое намутить в своих классах?
Проблема в том, что оператор -> должен возвращать указатель, т.е. конкретный адрес памяти.
А он, как я понимаю, не для всех экземпляров существует (что-то может быть размещено, например, непосредственно в регистрах ЦП).
Собственно нельзя получить указатель на rvalue

Код
C++ (Qt)
int * a = &3; // Error
 

Но и не нужен сам указатель, нужен просто доступ к rvalueMethod() без всяких cast и move.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #5 : Ноябрь 22, 2018, 18:18 »

А, я тупанул, да, там же указатель.
Как насчет попробовать сделать аналог std::reference_wrapper?
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #6 : Ноябрь 23, 2018, 08:01 »

А, я тупанул, да, там же указатель.
Как насчет попробовать сделать аналог std::reference_wrapper?

Собственно, и делаю такую библиотечку, куда входит набор враперов.
Хотел добиться абсолютной прозрачности API для  враперов, но похоже есть пока непреодолимые языковые ограничения.
В принципе, не очень критично, так как случай крайне редкий. Тем не менее - это является ограничением возможности их использования.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Ноябрь 23, 2018, 10:40 »

Имеется возможность реализовывать методы конкретно для rvalue и lvalue значений, например,

Код
C++ (Qt)
struct My
{
   void method () && {}
   void method () & {}
};
 

таким образом закладывать для rvalue экземпляров типа My более эффективную реализацию, или даже предусматривать разный api
Если я правильно понял, то "методы для lvalue" - это как сейчас/всегда, но что за "для rvalue" - без понятия. Что такое rvalue (и почему не имеет адреса) понимаю, но методы здесь причем? Можно больше пояснений/примерчик? Спасибо 
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #8 : Ноябрь 23, 2018, 11:31 »

Если я правильно понял, то "методы для lvalue" - это как сейчас/всегда, но что за "для rvalue" - без понятия. Что такое rvalue (и почему не имеет адреса) понимаю, но методы здесь причем? Можно больше пояснений/примерчик? Спасибо 

Вообще с стандарте C++  целый раздел есть по rvalue и вот неплохой материал для изучения
https://habr.com/post/322132/

Методы без уточнения &/&& одинаковы и для lvalue и rvalue значений.
К rvalue значениям относятся в том числе временные объекты, время жизни которых ограничено вызовами методов.
Факт того, что время жизни временного объекта скоротечно), может быть использован для реализации более эффективного кода (без лишних копирований, аллокаций и т.п.).
Предусмотрена возможность явного преобразования lvalue ссылки к rvalue с помощью ::std::move. В этом случае контроль времени жизни ложится на хрупкие плечи программиста).
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #9 : Ноябрь 23, 2018, 11:55 »

Так вот, что бы такое намутить в своих классах?
Проблема в том, что оператор -> должен возвращать указатель, т.е. конкретный адрес памяти.

Да, хоть operator-> и может возвращать промежуточные объекты, получается, что в конечном итоге на выходе всё равно подавай указатель, к содержимому которого идёт обращение как к lvalue. У меня тоже не получилось через operator-> добраться до rvalueMethod().

Или ждать возможного внедрения предложения в стандарт N3723 (ссылка вначале) или предложений для оператора "точка" (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4477.pdf , http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0352r1.pdf?

Надеяться, конечно, можно, но особых подвижек по operator dot что-то не замечаю. Может слишком долго ждать придётся Улыбающийся.
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Ноябрь 23, 2018, 13:56 »

Вообще с стандарте C++  целый раздел есть по rvalue и вот неплохой материал для изучения
https://habr.com/post/322132/
Ой Улыбающийся Может не стоит так-то, "через край" (все хорошо в меру, и изучение тонкостей языка тоже). А освободившееся время посвятить предметной части, не раз замечал что это гораздо эффективнее.
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #11 : Ноябрь 23, 2018, 23:55 »

Ой Улыбающийся Может не стоит так-то, "через край" (все хорошо в меру, и изучение тонкостей языка тоже). А освободившееся время посвятить предметной части, не раз замечал что это гораздо эффективнее.

Так это ж теперь одна из самых важных основ языка  Шокированный, особенно если пишется высокопроизводительный код  Смеющийся Смеющийся Смеющийся.
Предметная часть сама по себе важна, но не менее важно наличие простых, удобных и эффективных инструментов для преобразования предметной части в программное обеспечение.
А как только дело касается инструментов, то тонкости языка сами становятся предметной частью Подмигивающий
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Ноябрь 24, 2018, 07:59 »

Так это ж теперь одна из самых важных основ языка  Шокированный, особенно если пишется высокопроизводительный код  Смеющийся Смеющийся Смеющийся.
Преувеличение. Просто не хватает терпения, аккуратности. Сначала бузует все по значению ( QString ), а потом начинает "мувать". Как известно, чисто не там где убирают...

Статью "ни асилил"  Улыбающийся
Цитировать
std::string &&str = std::string("Hello");
std::string *psrt = &str;

Выясняется, что да, можно, так как str — lvalue, хотя его тип rvalue-ссылка. Запомните, это важно.
Ни фига не понял, что "физически" произошло? Кто (или где) сохранил строку "Hello"? Поясните. Спасибо
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #13 : Ноябрь 24, 2018, 12:09 »

Ни фига не понял, что "физически" произошло? Кто (или где) сохранил строку "Hello"? Поясните. Спасибо

Тут такая история. Что именно произошло - точно не известно. Давеча видел эту строку в тёмном переулке, что по адресу 0x7fffffffdf30. В угол забилась, string_view прикрылась, не шелохнется... авось никто не заметит.Времена-то после 11-го года суровые пошли. Могут кого угодно куда угодно переместить, да ещё и все внутренности при этом вынуть. Представляете?! Я мимо прошёл, сделал вид, что не заметил. И вы, пожалуйста, тоже про этот адрес больше никому не говорите! Строчку жалко  Плачущий...
Записан

Пока сам не сделаешь...
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #14 : Ноябрь 25, 2018, 22:06 »

Ни фига не понял, что "физически" произошло? Кто (или где) сохранил строку "Hello"? Поясните. Спасибо

Все что объявляется явно в виде переменной является lvalue значением указанного типа, у которого имеется конкретный адрес.
Сам тип значения может быть T (value), T& (lvalue) или T&& (rvalue). Ссылки тоже являются полноценными типами.
Для инициализации ссылочных типов с помощью временных объектов, стандартом оговорен механизм "продления жизни" возвращаемых значений.
Каким образом технически работает механизм "продления жизни" скрыто в недрах компилятора (может быть разным для разных компиляторов).
Таким образом в примере представлен случай формирования экземпляра lvalue, типа rvalue ссылки на экземпляр значения с "продленной жизнью", возвращенный функцией std::string("Hello").
Записан
Страниц: [1] 2 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.19 секунд. Запросов: 22.