Re[19]: Получить сигнатуру из ламбды
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 18.08.20 10:01
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


O>> так typedef TYPE_OF_3_PARAMETER(func(int(), int(), int(), int())) third_parameter_type; ?\


TB>Ну например, только троечка должна быть параметром, а не частью имени, конечно же.

Отлично. Напиши, как ты это видишь?
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[20]: Получить сигнатуру из ламбды
От: T4r4sB Россия  
Дата: 18.08.20 10:13
Оценка:
Здравствуйте, ollv, Вы писали:

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


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


O>>> так typedef TYPE_OF_3_PARAMETER(func(int(), int(), int(), int())) third_parameter_type; ?\


TB>>Ну например, только троечка должна быть параметром, а не частью имени, конечно же.

O>Отлично. Напиши, как ты это видишь?
typedef TYPE_OF_PARAMETER(func(int(), int(), int(), int()), 3) third_parameter_type;
Re[7]: Получить сигнатуру из ламбды
От: Went  
Дата: 18.08.20 10:34
Оценка:
Здравствуйте, rg45, Вы писали:
R>А что препятствует переходу на что-то более свеженькое?
Да, коней на переправе не меняют. С новым проектом будет и новая студия. Не хочется тратить время на адаптацию перед релизом.
Re[21]: Получить сигнатуру из ламбды
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 18.08.20 10:36
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


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


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


O>>>> так typedef TYPE_OF_3_PARAMETER(func(int(), int(), int(), int())) third_parameter_type; ?\


TB>>>Ну например, только троечка должна быть параметром, а не частью имени, конечно же.

O>>Отлично. Напиши, как ты это видишь?
TB>
TB>typedef TYPE_OF_PARAMETER(func(int(), int(), int(), int()), 3) third_parameter_type;
TB>

погоди, так это плюсовой вариант и есть. Просто за макросом кое что будет написано. Но ты волен скипать это с глаз долой )
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[22]: Получить сигнатуру из ламбды
От: T4r4sB Россия  
Дата: 18.08.20 15:58
Оценка: :)
Здравствуйте, ollv, Вы писали:

O>погоди, так это плюсовой вариант и есть. Просто за макросом кое что будет написано.


Кое-что из 100 строк копипасты.
То есть если мне понадобится чуть иной вариант, то я должен писать свою копипасту.
Ну и без библиотек, хранящих тонны платформозависимых костылей на каждую платформу, на С++ по сути уже писать нельзя.
Re[4]: Получить сигнатуру из ламбды
От: Went  
Дата: 19.08.20 07:19
Оценка: +1 :)
Здравствуйте, night beast.
Жаль, std::apply только с С++17 появляется Ну, у меня есть велосипедный tuple_call.
Re[5]: Получить сигнатуру из ламбды
От: night beast СССР  
Дата: 19.08.20 07:33
Оценка:
Здравствуйте, Went, Вы писали:

W>Жаль, std::apply только с С++17 появляется Ну, у меня есть велосипедный tuple_call.


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

там кстати можно попробовать не тупл, а [args...] захватывать.
не знаю правда, сработает ли в 11 стандарте.
Re[23]: Получить сигнатуру из ламбды
От: ollv СССР https://youtu.be/DQDoYs6wHoo
Дата: 19.08.20 09:15
Оценка:
Здравствуйте, T4r4sB, Вы писали:

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


O>>погоди, так это плюсовой вариант и есть. Просто за макросом кое что будет написано.


TB>Кое-что из 100 строк копипасты.

Так необязательно смотреть этот код. А кейсы и их количество, ну извини пока экспоненциального роста кейсов не наблюдается никаких проблем я не вижу. Более того половина кода такого — генерится.
TB>То есть если мне понадобится чуть иной вариант, то я должен писать свою копипасту.
В нормальной библиотеке оч тяжело найти кейс который не покрыт. Если это самописная — можно подойти к тому кто саппортит этот код.
TB>Ну и без библиотек, хранящих тонны платформозависимых костылей на каждую платформу, на С++ по сути уже писать нельзя.
)) ха — смешно. А на чем можно ?
Compiler can be as trained AI but can't compose music.
Antheil piano jazz sonata. Я болен ПГМ.
Re[24]: Получить сигнатуру из ламбды
От: T4r4sB Россия  
Дата: 19.08.20 10:04
Оценка:
Здравствуйте, ollv, Вы писали:

O>Более того половина кода такого — генерится.


В С++ настолько развитое метапрограммирование, что приходится брать внешние генераторы.
Расстрелять комитет нахрен.
Re[3]: Получить сигнатуру из ламбды
От: Went  
Дата: 19.08.20 13:24
Оценка:
Здравствуйте. Короче, получилось что-то такое:

using namespace md;

namespace md {

void add_to_queue(const std::function<void()>& fnc)
{
  fnc(); // Для проверки просто вызываем
}

template<typename Sig>
struct defer_proxy
{
  template<typename... Args>
  void operator()(Args&&... args)
  {
    // Чтобы протащить в лямбду...
    stdext::call_traits<Sig>::parameter_types args_tuple(std::forward<Args>(args)...);  // Пакуем аргументы в туплу
    auto fn_ = std::move(fn);                                                           // И функцию в локал 

    add_to_queue([fn_, args_tuple](){stdext::call_elements(fn_, args_tuple);}); // call_elements = std::apply
  } 

  std::function<Sig> fn;
};


template<typename T>
auto defer(const T& fn) -> typename std::function<typename stdext::call_traits<T>::signature>
{
  return defer_proxy<typename stdext::call_traits<T>::signature>{fn};
}

} // md

int main(int argc, char * argv[])
{
  auto x = [](int i, float f)
  {
    std::cout << i << " " << f << std::endl;
  };
  defer(x)(1, 1.0f);

  std::function<void(int, float)> y = x;
  defer(y)(2, 2.0f);

  return 0;
}


Запустить "как есть" его не получится (call_traits и call_elements), но, может, будут какие-то замечания просто при взгляде на него?
Отредактировано 19.08.2020 13:31 Went (Разметка) . Предыдущая версия .
Re[4]: Получить сигнатуру из ламбды
От: rg45 СССР  
Дата: 19.08.20 13:36
Оценка:
Здравствуйте, Went, Вы писали:

W>Запустить "как есть" его не получится (call_traits и call_elements), но, может, будут какие-то замечания просто при взгляде на него?


Я бы предложил сделать такое упрощение
    add_to_queue([fn_ = std::move(fn), args_tuple](){stdext::call_elements(fn_, args_tuple);});} // call_elements = std::apply

А то выходит, что ты сначала делаешь move и тут же копирование.

И второе, несколько смущает такая одноразовость объектов defer_proxy. Повторное использование чревато UB. Я бы подумал, как можно обезопасить код.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 19.08.2020 13:38 rg45 . Предыдущая версия .
Re[4]: Получить сигнатуру из ламбды
От: night beast СССР  
Дата: 19.08.20 13:37
Оценка:
Здравствуйте, Went, Вы писали:

W>Здравствуйте. Короче, получилось что-то такое:


W>Запустить "как есть" его не получится (call_traits и call_elements), но, может, будут какие-то замечания просто при взгляде на него?


вроде бы [fn, args...]() { fn_(std::move(args)...); }
должно сработать.
Отредактировано 19.08.2020 13:37 night beast . Предыдущая версия .
Re[5]: Получить сигнатуру из ламбды
От: rg45 СССР  
Дата: 19.08.20 13:46
Оценка:
Здравствуйте, night beast, Вы писали:

NB>вроде бы [fn, args...]() { fn_(std::move(args)...); }

NB>должно сработать.

В результате move можно получить нежелательное преобразование к rvalue и нарваться на несовместимость фактических и формальных параметров.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 19.08.2020 13:48 rg45 . Предыдущая версия .
Re[6]: Получить сигнатуру из ламбды
От: night beast СССР  
Дата: 19.08.20 14:23
Оценка:
Здравствуйте, rg45, Вы писали:

NB>>вроде бы [fn, args...]() { fn_(std::move(args)...); }

NB>>должно сработать.

R>В результате move можно получить нежелательное преобразование к rvalue и нарваться на несовместимость фактических и формальных параметров.


в какой ситуации? если параметр не const ссылка? тогда и захват значения смысла иметь не будет.
Re[4]: Получить сигнатуру из ламбды
От: rg45 СССР  
Дата: 19.08.20 14:58
Оценка:
Здравствуйте, Went, Вы писали:

W>Запустить "как есть" его не получится (call_traits и call_elements), но, может, будут какие-то замечания просто при взгляде на него?


Виталик, а можешь объяснить, чем не устраивает "лобовой" вариант? Повторный вызов defer_proxy ведь у тебя все равно невозможен (UB), так какой смысл отделять функтор от параметров?

http://coliru.stacked-crooked.com/a/be68f70b50a6c00b

#include <iostream>
#include <functional>

namespace md {

void add_to_queue(const std::function<void()>& fnc)
{
  fnc(); // Для проверки просто вызываем
}

template<typename F, typename...Args>
void defer(F&& fn, Args&&...args)
{
  return add_to_queue([=](){fn(args...);});
}

} // md

int main(int argc, char * argv[])
{
  auto x = [](int i, float f)
  {
    std::cout << i << " " << f << std::endl;
  };
  md::defer(x, 1, 1.0f);

  std::function<void(int, float)> y = x;
  md::defer(y, 2, 2.0f);
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Получить сигнатуру из ламбды
От: rg45 СССР  
Дата: 19.08.20 15:42
Оценка: 4 (1)
Здравствуйте, Went, Вы писали:

W>Запустить "как есть" его не получится (call_traits и call_elements), но, может, будут какие-то замечания просто при взгляде на него?


Вот тебе еще один вариант. В точности в твоей постановке, но гораздо проще в реализации, без туплов и всяких мета-чудес:

http://coliru.stacked-crooked.com/a/3f41b4c768c465c2

#include <iostream>
#include <functional>

namespace md {

void add_to_queue(const std::function<void()>& fnc)
{
  fnc(); // Для проверки просто вызываем
}

template<typename F>
struct defer_proxy
{
  template<typename... Args>
  void operator()(Args&&... args) const
  {
    auto&& fn_ = fn;
    add_to_queue([=](){fn_(args...);}); // call_elements = std::apply
  } 
  F fn;
};


template<typename F>
defer_proxy<F> defer(const F& fn)
{
  return {fn};
}

} // md

int main(int argc, char * argv[])
{
  auto x = [](int i, float f)
  {
    std::cout << i << " " << f << std::endl;
  };
  md::defer(x)(1, 1.0f);

  std::function<void(int, float)> y = x;
  md::defer(y)(2, 2.0f);
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 19.08.2020 15:48 rg45 . Предыдущая версия .
Re[5]: Получить сигнатуру из ламбды
От: Went  
Дата: 19.08.20 16:21
Оценка:
Здравствуйте, rg45, Вы писали:
R>Я бы предложил сделать такое упрощение
R>
R>    add_to_queue([fn_ = std::move(fn), args_tuple](){stdext::call_elements(fn_, args_tuple);});} // call_elements = std::apply
R>

R>А то выходит, что ты сначала делаешь move и тут же копирование.
Увы, в С++11 присвоение внутри списков захвата не завезли...

R>И второе, несколько смущает такая одноразовость объектов defer_proxy. Повторное использование чревато UB. Я бы подумал, как можно обезопасить код.

Да, с одноразовостью я погорячился, ее там быть не должно. Придется делать обычное копирование, еще и 2 раза.
Re[5]: Получить сигнатуру из ламбды
От: Went  
Дата: 19.08.20 16:22
Оценка:
Здравствуйте, night beast, Вы писали:
NB>вроде бы [fn, args...]() { fn_(std::move(args)...); }
NB>должно сработать.
Проверю, но не уверен, что в С++11 есть захват паков параметров...
Re[6]: Получить сигнатуру из ламбды
От: rg45 СССР  
Дата: 19.08.20 16:31
Оценка:
Здравствуйте, Went, Вы писали:

W>Да, с одноразовостью я погорячился, ее там быть не должно. Придется делать обычное копирование, еще и 2 раза.


Ты локальный fn_ можешь сделать ссылкой на мембер. Лямбда все равно по значению его возьмет.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 19.08.2020 16:34 rg45 . Предыдущая версия .
Re[5]: Получить сигнатуру из ламбды
От: Went  
Дата: 19.08.20 16:33
Оценка: 1 (1)
Здравствуйте, rg45, Вы писали:
R>Виталик, а можешь объяснить, чем не устраивает "лобовой" вариант? Повторный вызов defer_proxy ведь у тебя все равно невозможен (UB), так какой смысл отделять функтор от параметров?
R>http://coliru.stacked-crooked.com/a/be68f70b50a6c00b
Во-первых, я погорячился, и повторный вызов должен работать корректно
Во-вторых, вызов функции defer не должен добавлять вызов в список сразу, а должен создавать функцию эквивалентной сигнатуры, вызов которой уже "сбиндит" прокси-функцию и положит ее в очередь обработки.
Вот небольшой пример использования (функции и классы из головы):
// Какая-то демо-функция
void log(std::string text)
{
  log() << text;
}

Socket<void(std::string)> n_input;

int main()
{
  // Это код вызовет запись в лог немедленно
  n_input.connect(&log);
  n_input("Instant notification"); // То есть после этой строчки в логе уже надпись "Instant notification"
  n_input.disconnect_all();

  // А этот код покладет запись в лог в очередь, которая обработается "когда-то потом"
  n_input.connect(defer(&log));
  n_input("Defered notification"); // То есть после этой строчки в логе сразу ничего не появится

  process_queue(); // А после этой строчки - в логе появится "Defered notification"
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.