Consider the next sample of the code:
template <typename... TArgs>
void foo(std::function<void(TArgs...)> f) {
}
template <typename... TArgs>
class Class {
public:
static void foo(std::function<void(TArgs...)> f) {
}
};
Why can I do this:
int main() {
// Helper class call
Class<int, int>::foo(
[](int a, int b) {}
);
}
But I get a compile error doing this:
int main() {
// Function call
foo<int, int>(
[](int a, int b) {}
);
}
I just want to have a convenient way to use functions such as foo
.
I've tried this:
std::function<void(int, int)> f = [](int a, int b) {
};
foo<int, int>(f); // ok
And it worked. And this is ok. But I want to know if there is any way to use lambdas right in the function call, without creating a local function object.
CodePudding user response:
Because of this: Why is template parameter pack used in a function argument type as its template argument list not able to be explicit specified
When you call foo<int, int>([](int a, int b) {});
, the pack TArgs
is still deduced in case it needs to be extended. std::function<void(TArgs...)>
cannot deduce anything for TArgs...
with a lambda argument, so it gets deduced as an empty pack, which conflicts with the given int, int
.
For Class<int, int>::foo
, there is no template argument deduction since the template arguments are already given.
A fix for this is to put it in a non-deduced context:
template <typename... TArgs>
void foo(std::type_identity_t<std::function<void(TArgs...)>> f) {
}
Or don't take a std::function
at all:
template <typename F>
void foo(F&& f) {
}