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?