Reputation: 76240
I have to write a function that will be used as:
obj.transform([](x& a, y& b) { ... });
obj.transform([](x& a) { ... });
obj.transform([](y const& a, x& b, z const& c) { ... });
obj.transform([a, b](z const& c) { ... });
...
and inside the function declaration, I need to figure out the type of the arguments passed in.
The body of the function is then in the form (assuming x
to be a member object and argfn
the function passed in):
if (x.mfn1<std::remove_reference_t<Args>...>())
argfn(x.mfn2<std::remove_reference_t<Args>>()...);
If you are asking yourself, why and you have no idea how this could be useful, or if you think this is an XY problem, then you can find the context right here.
Attempt #1
template<typename... Args>
void fn(std::function<void(Args...)>) { ... }
This doesn't work because there's apparently no way to have a conversion between that std::function
and any lambda.
Attempt #2
template<typename... Args>
void fn(void(*)(Args...)) { ... }
This works with the first, second and third example above (prepending +
on each lambda to force a conversion to pointer to function), but fails on the fourth.
Upvotes: 2
Views: 167
Reputation: 146910
It's impossible. For example, what if the argument is a functor containing a templated (especially variadic) operator()
? Or one that is overloaded? What are the "arguments" then?
The core problem here is that you're effectively re-implementing ranges but worse. Just offer plain iterators over the entities and then use std::transform
. Or find a range library of your choice.
Upvotes: 1