2

Problem

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>>()...); 

Context

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.

My attempts

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.

14
  • 2
    Have a look at github.com/kennytm/utils/blob/master/traits.hpp Commented Apr 25, 2015 at 11:44
  • So, you pass in callables, deduce the types needed to call it, check if you have those types, and then invoke. That implies that you can only ever have one object of a given type in your entity, which seems like a strange restriction. Two small changes to your linked code make it compile. Commented Apr 25, 2015 at 13:16
  • You need the argument types? If the lambda isn't generic, just look at its operator(). Commented Apr 25, 2015 at 13:18
  • To be insane, the dual of an entity is of type any(any) -> (any|typeerror) (to mix haskell and C++ function notation horribly). Curry incoming functions, feed to duals of entities, done? Naw, doesn't work, as mapping auto(auto) to any(any) isn't feasible, and finding what entity dual to call requires linear search of the entities. Both can be fixed, but basically involve manual or automatic signature deduction, which make it silly. Commented Apr 25, 2015 at 13:52
  • @Yakk "That implies that you can only ever have one object of a given type in your entity, which seems like a strange restriction." What do you mean? With that given code, every entity can contain any number of other object types. Commented Apr 25, 2015 at 15:17

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

"what if the argument is a functor containing a templated (especially variadic) operator()", I'm fine with that failing with a compile error in the forms of "cannot deduce type ...".

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.