1

I'm in a bit of a pickle, following up my previous question and using a code similar to the one I posted here.

  1. I use a variadic template function which accepts variadic objects
  2. It packs them into a tuple
  3. Iterates them using the visitor idiom
  4. Binds for each object a callback

Instead of the original minified example shown below:

template <typename... Args> void make_classes(Args... args) { auto t = std::tuple<Args...>(args...); unsigned int size = std::tuple_size<decltype(t)>::value; auto execute = [](auto & obj){ obj.operator()(); }; for (int i = 0; i < size; i++) { visit_at(t, i, execute); } } 

I am trying to understand how I can deduce the template type of the auto lambda, so that I can bind it:

template <typename... Args> void make_classes(Args... args) { auto t = std::tuple<Args...>(args...); unsigned int size = std::tuple_size<decltype(t)>::value; auto execute = [](auto & obj){ // obtain type of obj as T? auto callback = std::bind(&T::deserialise, obj, std::placeholders::_1); // do something else here using this callback. }; for (int i = 0; i < size; i++) { visit_at(t, i, execute); } } 

There's a catch: the parameter objects are non-copyable (although I could change that), but I would like to know if/how the above could work by deducing the template type packed in the tuple as obtained by the visitor.

If I can't deduce the type inside the lambda, can I somehow store it within the tuple (e.g.,: type & object) in order to later extract it?

4
  • Don't you need decltype(auto)? Commented Aug 30, 2016 at 16:37
  • @NathanOliver I don't know, how would that work? Commented Aug 30, 2016 at 16:37
  • @NathanOliver seems you're on to something, using decltype(obj returns error: type 'decltype(obj)' cannot be used prior to '::' because it has no members with the correct type printed in the error. Commented Aug 30, 2016 at 16:40
  • 1
    Oops. typo. If you want the type of obj then you just use decltype(obj). Commented Aug 30, 2016 at 16:40

1 Answer 1

6

Just use another lambda:

auto callback = [&obj](auto& x){ obj.deserialise(x); }; 

std::bind is rarely useful. (If you really want to copy obj, you can drop the leading &.)


Moreover, you don't actually need a tuple...

template <class F, class... Args> void for_each_arg(F&& f, Args&&... args) { using swallow = int[]; (void)swallow{0, (void(f(std::forward<Args>(args))), 0)... }; } template <typename... Args> void make_classes(Args... args) { for_each_arg([](auto& obj){ auto callback = [&obj](auto& x) { obj.deserialise(x); }; // do something with callback }, args...); } 
Sign up to request clarification or add additional context in comments.

2 Comments

wow many thanks, this is a lot simpler, will take some time to digest.
@Ælex See T.C.'s answer for a good explanation.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.