Метод класса, принимающий лямбда-выражения, представляющие функции различного числа аргументов - PullRequest
0 голосов
/ 09 января 2019

Я хотел бы передать функции в метод универсального класса, чтобы универсальный класс мог вызывать функции, не требующие аргументов, одного аргумента, двух аргументов и т. Д.

Я видел различные шаблоны, но мне не нравится синтаксис. Предыдущий вопрос SO рекомендовал передавать лямбда-выражения, упаковывая функцию:

https://stackoverflow.com/a/48976528/997112

где ответ:

void run_callback(std::function<void()>& func) 
{
    func();
}

run_callback([]{ func_without_params(); });

и поэтому я добавил метод, который не требует аргументов:

void func_without_params()
{
    std::cout << "x" << std::endl;
}

но когда я звоню:

run_callback([]{ func_without_params(); });

в VS2013 intellisense обнаруживает ошибку, и я получаю ошибку компилятора:

error C2664: 'void run_callback(std::function<void (void)> &)' :
cannot convert argument 1 from
'main::<lambda_de925f4d5cd926a8bb664f9c057a7a19>' to
'std::function<void (void)> &'

Что такое main::<lambda_de925f4d5cd926a8bb664f9c057a7a19> тип? Я не до конца понимаю ошибку.

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Что такое main::<lambda_de925f4d5cd926a8bb664f9c057a7a19> тип?

Какие ссылки говорят о лямбда-выражении:

Лямбда-выражение является prvalue-выражением уникального без имени не объединенный неагрегированный тип класса, известный как тип закрытия, который объявлено в наименьшей области блока , области действия класса или области имен который содержит лямбда-выражение.

без имени только для программистов, компилятор знает это имя, а в вашем случае lambda_de925f4d5cd926a8bb664f9c057a7a19 - это имя типа замыкания. main относится к функции, внутри которой был определен тип замыкания.

Вы можете использовать cppinsights , чтобы заглянуть за кулисы. cppinsights использует Clang, который не принимает привязку Rvalue к ссылке Lvalue, поэтому измените свой код на:

void run_callback(std::function<void()> func) // take by value

и вывод из cppinsights :

int main() { // scope of closure type

  class __lambda_14_16 { // closure type
    public: inline /*constexpr */ void operator()() const
    {
      func_without_params();
    }

  };

  run_callback(std::function<void ()>(__lambda_14_16{}));
}
0 голосов
/ 09 января 2019

За исключением злых расширений компилятора, вы не можете инициализировать неконстантную ссылку (параметр func) с чем-то, что не является l-значением. Сделайте параметр const:

#include <functional>
#include <iostream>

void run_callback(std::function<void()> const &func)
{
    func();
}

void func_without_params()
{
    std::cout << "x" << std::endl;
}

int main()
{
    run_callback([] { func_without_params(); });
}
...