In your example
LambdaClass<decltype(lambdaFunc)> lambdaClassObject<decltype(lambdaFunc)>(lambdaFunc);
the second template argument list is incorrect syntax. This needs to be just
LambdaClass<decltype(lambdaFunc)> lambdaClassObject(lambdaFunc);
So I am interested in first if this code is efficient in the sense that the compiler could inline the calls of the saved member lambda function
Yes, this class can be used in ways that will allow optimizations pretty much just like using a lambda directly. The template argument is the exact type of the lambda expression, and template substitution happens at compile time, usually giving results just like you would get by writing out code without using templates.
How one could write this code more beautiful?
@lubgr's answer already mentions the C++17 "class template deduction" and "deduction guide" features. Prior to C++17, the usual trick to avoid needing to specify class template arguments is a helper "make function":
template <typename F>
auto makeLambdaClass(F&& func) ->
LambdaClass<typename std::decay<F>::type>
{ return { std::forward<F>(func); } }
Now you can do
auto lambdaFunc = [](int _a) -> int { return _a; };
auto lambdaClassObject = makeLambdaClass(lambdaFunc);
But to go a step further and make
auto lambdaClassObject = makeLambdaClass( [](int _a) -> int { return _a; } );
also work, you'll also need to make sure the class has a constructor that accepts an rvalue, not just a non-const lvalue:
template<typename F>
class LambdaClass {
private:
F lambdaFunc;
public:
LambdaClass(const F &lambdaFunc_): lambdaFunc(lambdaFunc_) {}
LambdaClass(F &&lambdaFunc_) : lambdaFunc(std::move(lambdaFunc_)) {}
};
By the way, this class will work just as well with a callable class that is not a lambda's closure type, since a lambda is just a more convenient way of defining a class with an operator()
:
class UniqueUIntGenerator
{
public:
unsigned int operator()() const noexcept
{ return num++; }
private:
static unsigned int num;
};
unsigned int UniqueIntGenerator::num = 0;
LambdaClass<UniqueIntGenerator> gen{UniqueIntGenerator{}};
std::function
to make it assignable. – Bantamweight