Здравствуйте, Went, Вы писали:
W>Здравствуйте, Коваленко Дмитрий. W>Если я правильно понял, то сами реализации "знают" о ctx, и их методы сами эти реализации не меняют, а меняют в самом ctx.
В данном случае, да. Вы все правильно поняли.
Но дело в том, что этот интерфейс t_errors еще реализован в другом классе, объекты которого сами хранят добавляемые объекты.
То есть метод "virtual void add(int errCode)=0;" константным сделать нельзя.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Передача объекта, возвращаемого функцией, в другую функцию.
Здравствуйте, Коваленко Дмитрий, Вы писали: КД>Но дело в том, что этот интерфейс t_errors еще реализован в другом классе, объекты которого сами хранят добавляемые объекты. КД>То есть метод "virtual void add(int errCode)=0;" константным сделать нельзя.
Понятно... Ну, а написать
auto errors = ctx.get_errors_without_limits();
add_current_errors(errors);
нельзя?
Re[4]: Передача объекта, возвращаемого функцией, в другую функцию.
Здравствуйте, Went, Вы писали:
КД>>Но дело в том, что этот интерфейс t_errors еще реализован в другом классе, объекты которого сами хранят добавляемые объекты. КД>>То есть метод "virtual void add(int errCode)=0;" константным сделать нельзя. W>Понятно... Ну, а написать W>
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Досадно, что сценарий передачи временного объекта по неконстантной ссылке есть, а официального разрешения со стороны C++ нет
Как это нет? rvalue reference как раз для такого случая подходят. Просто добавь второй амперсанд и будет как надо:
void add_current_errors(t_errors&& errs);
И каждый день — без права на ошибку...
Re[6]: Передача объекта, возвращаемого функцией, в другую функцию.
Здравствуйте, B0FEE664, Вы писали:
КД>>Досадно, что сценарий передачи временного объекта по неконстантной ссылке есть, а официального разрешения со стороны C++ нет BFE>Как это нет? rvalue reference как раз для такого случая подходят. Просто добавь второй амперсанд и будет как надо: BFE>
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>--- КД>Досадно, что сценарий передачи временного объекта по неконстантной ссылке есть, а официального разрешения со стороны C++ нет
Ну ОК, я могу предложить еще один способ забиндить временный объект к неконстантной ссылке. Я не хотел его показыать, поскольку он не совсем безопасен. Но, похоже, что для тебя этот способ хорошо подойдет, поскольку он вполне легален, и не требует добавления дополнительных перегрузок.
1. Определяем общую утилитную функцию make_lvalue (имя выбрать по вкусу):
Замечу, на всякий случай, T&& здесь — это так называемая форвардная ссылка, хоть по внешнему виду и выглядит как rvalue ссылка. Этот параметр абсолютно всеяден и может быть сопоставлен абсолютно любой категории выражений, не только rvalue, но и lvalue. Таким образом, эта функция абсолютно универсальна и отработает во всех случаях как надо. Небезопасность этой функции в том, что можно получать мертвые ссылки, если пользоваться ею бездумно. В то же время эта функция всегда будет безопасной при использовании в качестве подвыражения в составе других выражений.
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>В моей башке rvalue reference связано с перемещением состояния объекта. КД>А я мне тут ничего перемещать не надо
А в моей голове rvalue reference связана именно со временными объектами, хотя многие считают такую связь альтернативно одарённой, так что настаивать не буду, дабы не провоцировать свидетелей value category.
И каждый день — без права на ошибку...
Re: Передача объекта, возвращаемого функцией, в другую функцию.
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Привет всем.
КД>Есть интерфейс t_errors.
КД>У него две реализации — t_errors_without_limits и t_errors_with_limits
КД>Есть два метода, возвращающие экземпляры этих реализацией: КД>
КД>Все компилируется (VC++) и работает как и ожидается.
КД>При включенном 4-ом уровне предупреждений, компилятор предупреждает, что нельзя передавать по ссылке результат метода.
КД>Когда включаешь режим 'совместимости/соответствия' (Conformance Mode=Yes), компилятор отказывается компилировать.
КД>Переделал так: КД>
КД>Все откомпилировалось и работает без проблем. Предупреждений 4-го уровня тоже нет.
КД>Где-то в глубине души меня беспокоит такая конструкция func1(&func2()). Но она компилируется и работает. То есть, временный объект, возвращаемый из func2, живет до конца вызова func1.
КД>Как сделать лучше — не знаю.
КД>Собственно вопрос — это нормальный подход или могут возникнуть проблем?
КД>Еще раз отмечу, что add_current_errors указатель/ссылку на t_errors внутри не запоминает.
сдается мне, что предложенные солюшены небезопасны, либо при обновлении очередного компилятора МС приведут к потере компилябильности.
Такое поведение (продление жизни ссылки как для параметров так и для rvlue) сугубо майкрософт специфик, причем в последних версиях это может не работать.
Имхо просто врапперок над
add_current_errors что-то типа
template <typename Exc>
add_current_errors_fwd(Exc&& exc) {
add_current_errors(std::forward(exc));
}
поможет и код сохранить и особых нагрузок не добавит.
если это все идет в обощенную часть, можно и add_current_errors перегрузить для некоего враппера а из ctx.get_errors_w..._limits
мувать.
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[6]: Передача объекта, возвращаемого функцией, в другую фу
Здравствуйте, rg45, Вы писали:
КД>>Досадно, что сценарий передачи временного объекта по неконстантной ссылке есть, а официального разрешения со стороны C++ нет
R>Ну ОК, я могу предложить еще один способ забиндить временный объект к неконстантной ссылке. Я не хотел его показыать, поскольку он не совсем безопасен. Но, похоже, что для тебя этот способ хорошо подойдет, поскольку он вполне легален, и не требует добавления дополнительных перегрузок.
R>1. Определяем общую утилитную функцию make_lvalue (имя выбрать по вкусу):
КД>Отлично, просто отлично. КД>Имя оставил как есть.
С именами здесь можно было бы и поприкалываться. Если следовать логике стандарной библиотеки, эта функция должна бы называться unmove, ибо она выполняет преобразование, обратное тому, которое выполняет std::move
--
Re[8]: Передача объекта, возвращаемого функцией, в другую фу
Здравствуйте, rg45, Вы писали:
КД>>Имя оставил как есть.
R>С именами здесь можно было бы и поприкалываться. Если следовать логике стандарной библиотеки, эта функция должна бы называться unmove, ибо она выполняет преобразование, обратное тому, которое выполняет std::move
Небольшой хак, форсирующий rvalue-reference до lvalue
template<class T>
T& var_cast(T&& var) { return var; }
...
A var;
const A cvar;
A val();
const A cval();
A& ref();
const A& cref();
void accept(A& r);
...
// всё ок
accept(var_cast(var));
accept(var_cast(val()));
accept(var_cast(ref()));
// не скомпилируется - результат имеет тип const A&
accept(var_cast(cvar));
accept(var_cast(cval()));
accept(var_cast(cref()));
Перекуём баги на фичи!
Re[7]: Передача объекта, возвращаемого функцией, в другую функцию.
Здравствуйте, Коваленко Дмитрий, Вы писали: КД>Здравствуйте, B0FEE664, Вы писали: КД>>>Досадно, что сценарий передачи временного объекта по неконстантной ссылке есть, а официального разрешения со стороны C++ нет BFE>>Как это нет? rvalue reference как раз для такого случая подходят. Просто добавь второй амперсанд и будет как надо: BFE>>
КД>В моей башке rvalue reference связано с перемещением состояния объекта. КД>А я мне тут ничего перемещать не надо
Есть такая замечательная штука, как RVO (Return Value Optimization). Которая позволяет не вызывать лишний раз конструктор копии или перемещения и передавать rvalue туда, где объект будет использоваться.
Я твой код немного модифицировал. Объявил add_error как void add_error(t_errors&& errs,int const errCode) и добавил вывод информации о некоторых функциях, об адресе и типе объектов, конструктор копии и деструктор, что бы было видно, когда они вызовутся.
Как видишь, адреса в конструкторе и в add_error() совпадают и конструктор копии не вызывается, т.е. — функция add_error() использует тот-же объект, который был возвращён из ctx.get_errors_without_limits() или ctx.get_errors_with_limits(). А при выходе из add_error() объект разрушается.
rvalue может использоваться не только для перемещения, но и для RVO.
А если объявить add_error как void add_error(t_errors& errs,int const errCode), то GCC ругается
rsdn.cpp: In function ‘int main()’:
rsdn.cpp:136:41: error: invalid initialization of non-const reference of type ‘t_errors&’ from an rvalue of type ‘t_errors’
add_error(ctx.get_errors_without_limits(),1);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
rsdn.cpp:121:6: note: initializing argument 1 of ‘void add_error(t_errors&, int)’
void add_error(t_errors& errs,int const errCode)
^~~~~~~~~
rsdn.cpp:138:38: error: invalid initialization of non-const reference of type ‘t_errors&’ from an rvalue of type ‘t_errors’
add_error(ctx.get_errors_with_limits(),2);
~~~~~~~~~~~~~~~~~~~~~~~~~~^~
rsdn.cpp:121:6: note: initializing argument 1 of ‘void add_error(t_errors&, int)’
void add_error(t_errors& errs,int const errCode)
^~~~~~~~~
Re[8]: Передача объекта, возвращаемого функцией, в другую функцию.
Спасибо за проведенный анализ проблемы.
AN>rvalue может использоваться не только для перемещения, но и для RVO.
Сначала у меня что-то в голове сдвинулось, но потом я понял, что в моем случае лучше сидеть на make_lvalue, предложенном rg45
У меня в add_error(errs,errCode) передаются как временные объекты (полученные из функций get_xxxx()), так и локальные. Поэтому параметр errs определен как ссылка.
add_error(errs,errCode) — может быть виртуальным методом. Поэтому его нельзя определить как шаблон.
---
Решение с make_lvalue уже "ушло в HEAD" и прошло нагрузочное тестирование
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[9]: Передача объекта, возвращаемого функцией, в другую фу
КД>Сначала у меня что-то в голове сдвинулось, но потом я понял, что в моем случае лучше сидеть на make_lvalue, предложенном rg45 КД>Решение с make_lvalue уже "ушло в HEAD" и прошло нагрузочное тестирование
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Привет всем.
КД>Есть интерфейс t_errors.
КД>У него две реализации — t_errors_without_limits и t_errors_with_limits
КД>Есть два метода, возвращающие экземпляры этих реализацией: КД>
в старых плюсах это чистое UB. Передача ссылки на временный объект на стеке, время жизни которого закончилось. В новых плюсах есть расширение времени жизни переменной. Но оно весьма ограничено. Ты уверен, что оно здесь сработало? см. мой вопрос — народ утверждает, что расширение времени жизни переменной через rvalue не работает. см. мой вопрос
Здравствуйте, AndrewJD, Вы писали:
NB>>то что оно собирается в принципе -- это следствие того что когда-то майкрософт забил на стандарт.
AJD>У них это было еще когда стандарта не существовало.
после выхода стандарта у них была куча времени это поправить.
Re[8]: Передача объекта, возвращаемого функцией, в другую фу