Constantine
Ну там совершенная глупость
Constantine
Просто опущен простейший параметр
Constantine
Который напрямую отправляется на сигнатуру operator ()
Constantine
там в действительности типовое button.reset_is_enabled( utils::reactive::make_binary_function( utils::create(SomeSource1), utils::create(SomeSource2), [](auto value1, auto value2) { return some condition with value1 and value2; } ) )
Constantine
ну вот совсем не хочется на каждое такое С-стайлом функцию объявлять
Constantine
это не про предложение
Constantine
к предложению относится буквально то, что в комментариях
Constantine
вопрос: зачем нужен && для функций?
Constantine
ответ: потому что однократно вызываемая функция вызывается как call_once(once_callable_function<std::unique_ptr<int>()>&& function)
Constantine
Именно
Constantine
Лямбда МОЖЕТ быть разрушена вызовом
Constantine
operator ()
Constantine
?
Constantine
у меня лямбда захватила std::unique_ptr
Constantine
и хочет вернуть
Constantine
ага
Constantine
если бы это была не лямбда, я бы писал сигнатуру &&
Constantine
а лямбде не могу
Constantine
потому что нет ref quailfier
Constantine
я могу написать
Constantine
а еще я могу написать T& operator [](size_t ndx)
Constantine
Я не вызываю лямбду руками, я врапаю ее в once_callable_function
Constantine
И мне принципиально знать, что эту лямбду можно врапать в once_callable_function и нельзя в multiple_callable_move_constructible_function
Constantine
разница между ними очень простая - первая на самом деле аналогична вызову в non-member версии void inlambda_call_operator(closure_class&& this_reference)
Constantine
а вторая void inlambda_call_operator(closure_class& this_reference)
Constantine
Я использую лямбды в том числе для того, чтобы записывать builder объекты и передавать события на основной поток
Constantine
Где builder по определению once callable factory
Anatoliy
у меня лямбда захватила std::unique_ptr
это делается вот так: http://coliru.stacked-crooked.com/a/6436697af3823679 или я что-то упускаю?
Constantine
это делается вот так: http://coliru.stacked-crooked.com/a/6436697af3823679 или я что-то упускаю?
да, делается, но вот вопрос - как отличить ЭТУ лямбду от лямбды, которая инкрементает счетчик?
Constantine
просто ощути разницу template <typename T> struct builder_interface { virtual T build() && = 0; }; и template <typename T> struct every_object_is_registered_factory_interface { virtual T create() = 0; };
Anatoliy
virtual - это существенно?
Constantine
это интерфейс
Anatoliy
builder_interface или every_object_is_registered_factory_interface имеют поля?
Constantine
теперь подумай, соответствует ли auto x = std::make_unique< int >(42); auto l = [x = std::move(x)] () mutable -> auto { return std::move(x); }; первому и соответствует ли второму
Anatoliy
или можно вообще от виртуальности избавиться
Anatoliy
я пока задачи не вижу. только намёки
Constantine
задача: у тебя существует два типа функций. Один из этих типов можно вызывать много раз, другой тип - не более одного раза
Anatoliy
auto x = std::make_unique< int >(42); auto l = [x = std::move(x)] () mutable -> auto { assert(x); return std::move(x); };
Constantine
а теперь представь
Constantine
auto x = std::make_unique< int>(42); auto l = [x = std::move(x)] () mutable && -> auto { return std::move(x); };
Constantine
где && означает, что у лямбды operator () имеет ref qualifier &&
Constantine
что это даёт?
то, что синтаксис вызова лямбды - только по &&
Anatoliy
это тебя обяжет делать так: std::move(l)(). вот и всё
Constantine
это значит, что теперь не lambda(), а std::move(lambda)()
Constantine
именно
Anatoliy
волшебства не произойдёт
Constantine
произойдет
Anatoliy
нет.
Constantine
потому что std::move на одну переменную нехрен писать дважды
Anatoliy
у тебя даже нет ворнинга, чтобы задетектить use after move
Constantine
но у меня не тупая обезьяна за монитором
Constantine
а еще у меня есть типы-обертки
Constantine
которые в случае вызова lambda() просто это не скушают
Constantine
Как только я пишу mutable, я не имею в виду чистую функцию
Constantine
давайте вернемся к примеру
Constantine
просто ощути разницу template <typename T> struct builder_interface { virtual T build() && = 0; }; и template <typename T> struct every_object_is_registered_factory_interface { virtual T create() = 0; };
Constantine
это интерфейсы
Constantine
в том самом джава смысле
Anatoliy
у тебя даже нет ворнинга, чтобы задетектить use after move
https://stackoverflow.com/questions/36152183/warning-when-rvalue-declared-variable-goes-out-of-scope-being-not-moved-from
Anatoliy
как раз наоборот
Anatoliy
const у функций-членов значит, что чистая
Anatoliy
не распознал
Constantine
короче, && это та же самая разница, что в примере template <typename T> T build(builder_interface<T>&& builder); template <typename T> T create(factory_interface<T> & factory);
Constantine
На самом деле ref-qualifier это почти буквально переданный *this
Ivan
я может чего не догоняю, но Константин хотел это? https://ideone.com/t6PjSv
Constantine
я может чего не догоняю, но Константин хотел это? https://ideone.com/t6PjSv
я хочу более строгую проверку, ну хватит пихать мне менее строгий вариант
Constantine
ref-qualifier это буквально более строгая конвенция вызова
Constantine
во всех случаях
Ivan
ты хочешь чтобы у функции был такой тип: "функция вызываемая один раз"
Constantine
да
Ivan
и была бы ошибка компиляции если бы её вызвали два раза?
Ivan
из кода
Constantine
это невозможно достичь