Inspired by this question, I would like to compare the use of c++20 template lambda with a functor having a template operator().
As a test case, consider a template function call which takes a template lambda as an argument, and call this lambda instantiating it with some template parameters. The following c++20 code exemplifies the idea.
#include <tuple>
#include <utility>
template <int I, class Lambda, class... ArgsType>
void call(Lambda&& F, ArgsType&& ...args)
{
F.template operator()<I>(std::forward<ArgsType>(args)...);
}
int main() {
std::tuple<int, double, int> t{0,0,0};
int a = 2;
auto f = [&]<int I>(auto& x) { std::get<I>(x) += I + a; };
call<0>(f, t);
return 0;
}
In c++11/c++14/c++17, not having template lambda, the same task can be implemented with a functor, having a template operator(), as in the following code.
#include <tuple>
#include <utility>
template <int I, class Lambda, class... ArgsType>
void call(Lambda&& F, ArgsType&& ...args)
{
F.template operator()<I>(std::forward<ArgsType>(args)...);
}
struct Functor {
template <int I, class T>
void operator()(const int& a, T& x) { std::get<I>(x) += I + a; };
};
int main() {
std::tuple<int, double, int> t{0,0,0};
int a = 2;
Functor func{};
call<0>(func, a, t);
}
The main disadvantage I see in the second example is that, to emulate the lambda capture, one needs to pass explicitly all local variables (in this case int a) to the functor. This can be tedious, if Functor::operator() needs many variables from its "owner". Eventually, one could also perhaps pass the pointer this to Functor::operator().
No such complications are present in the c++20 example, where the lambda capture takes care of capturing the needed variables.
Aside from simplicity, is there any other concrete difference between the two approaches outlined above? What about the efficiency?