2

I would like to pass functions in to a generic class method, so the generic class can invoke functions requiring no args, one arg, two args etc.

I have seen variadic templates but I do not like the syntax. A previous SO question recommended passing lambdas, wrapping the function:

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

where the answer is:

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

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

and I therefore added a method which requires no argument:

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

but when I call:

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

in VS2013 the intellisense detects an error and i get the compiler error:

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

What is a main::<lambda_de925f4d5cd926a8bb664f9c057a7a19> type? I don't fully-understand the error.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
user997112
  • 29,025
  • 43
  • 182
  • 361

2 Answers2

3

Except for evil compiler extensions you cannot initialize a non-const reference (parameter func) with something that is not an l-value. Make the parameter 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(); });
}
Swordfish
  • 12,971
  • 3
  • 21
  • 43
1

What is a main::<lambda_de925f4d5cd926a8bb664f9c057a7a19> type?

What references says about lambda expression:

The lambda expression is a prvalue expression of unique unnamed non-union non-aggregate class type, known as closure type, which is declared in the smallest block scope, class scope, or namespace scope that contains the lambda expression.

unnamed only for programmers, compiler knows this name and in your case lambda_de925f4d5cd926a8bb664f9c057a7a19 is the name of closure type. main refers to the function inside which closure type was defined.

You can use cppinsights to look behind the scenes. cppinsights uses Clang which doesn't accept binding Rvalue to Lvalue reference, so change your code into:

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

and the output from cppinsights is:

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{}));
}
rafix07
  • 20,001
  • 3
  • 20
  • 33