Boiled down example of what I wanted to do:
auto callable = [](auto x, auto y = 0){return x + y;};
On it's own it compiles, and callable(1, 2)
works as expected, but callable(3)
gives a compilation error:
error: no match for call to '(f()::<lambda(auto:1, auto:2)>) (int)'
This is not an issue with lambdas specifically, same thing happens with generic functions with default argument
If callable
was a function (template), then callable<int, int>(3)
would work
For lambdas this workaround becomes a bit uglier:
callable.operator()<int, int>(3)
What I originally thought would happen under the hood:
struct Callable {
auto operator()(auto x, auto y){return x + y;}
auto operator()(auto x){return this->operator()(x, 0);}
};
As in, I was expecting the lambda to behave like Callable{}
And Callable callable;
is nice regarding the mentioned behaviour, both callable(1, 2)
and callable(3)
compile
This "unraveled" lambda-esque struct solution could work for my case, but I have some issues with it:
- My actual use for this is significantly more complicated than the boiled down example, and trying to use the struct solution would be a PITA
- I'm using C++20, the solution doesn't feel very modern, aesthetically it reminds me of emulating C++20 functionalities in C++11
To sum this up:
- I want an object
callable
- I want the expression
callable(a, b)
to compile to user-specified implementation
In the example above the implementation wasreturn a + b;
but I obviously don't care about addition specifically callable(a, b)
should be generic, meaning it should be invokable with various types of arguments (as long as the user-specified implementation permits it)- I want the expression
callable(a)
to compile and to be equivalent tocallable(a, 0)
callable(a)
should again be generic- I STRONGLY prefer solutions in which
callable
is a lambda
If I remove the requirements (4) and (5) this is trivially doable with a lambda
All examples mentioned on godbolt
NOTE: default arguments with lambdas work if they aren't generic [](int x, int y = 0){return x+y;}
Tried generic lambda, didn't work
Tried generic function, didn't work
Tried unrolled lambda via struct, works but not that great