5

I'm writing a library which involves a good amount of both template trickery and boost::any. I've run into a situation where I essentially have this:

boost::any a1, a2, a3, a4;

... and I need to call a function which looks like this:

template <typename A1, typename A2, typename A3, typename A4>
void somefunc (A1 a1, A2 a2, A3 a3, A4 a4);

I could resort to an obscenely nested series of if statements, but assuming I'm handling 10 distinct types, that's 10,000 if statements! Boost preprocessor could help here, but this is still a horrible solution.

Is there a better way to call a templated function with the contents of a boost::any without resorting to this sort of madness? As far as I can tell, there is not.

Xeo
  • 129,499
  • 52
  • 291
  • 397
Xtapolapocetl
  • 613
  • 5
  • 21
  • Only the user of the `boost::any` instance can get the exact value out at runtime (supplying a hardcoded type), you cannot call that function with the value contained within `boost::any` because it's type was *erased* at compile-time. What is the bigger problem you are trying to solve? `boost::any` is pretty low-level stuff. – GManNickG Feb 27 '13 at 00:38
  • 3
    Have all the `any` objects as one object, and when setting them all at once, also safe a pointer to the correct `somefunc` instantiation (e.g. `&somefunc`). – Xeo Feb 27 '13 at 00:40
  • @GManNickG the bigger problem I'm trying to solve involves auto-generation of Lua bindings on one side, and a boost::any holding the result from an arbitrary asynchronous function. Neither one can be replaced with the other in this situation. – Xtapolapocetl Feb 27 '13 at 00:56
  • @Xeo hey, that idea actually has some potential. Thanks, I'll think about that a little. – Xtapolapocetl Feb 27 '13 at 00:57
  • @Xeo on further reflection, that's a fantastic solution to my problem. Can you post it as an answer? – Xtapolapocetl Feb 27 '13 at 01:06

1 Answers1

10

If all your any objects can be set at the same time, you can just hard-code the type for the function pointer then and there. Stuff it all into a seperate object and you're good to go. This is basically a double-take on type-erasure, and could also be implemented through virtual functions (like how boost::any works internally), but I like this version more:

// note that this can easily be adapted to boost::tuple and variadic templates
struct any_container{
  template<class T1, class T3, class T3>
  any_container(T1 const& a1, T2 const& a2, T3 const& a3)
    : _ichi(a1), _ni(a2), _san(a3), _somefunc(&somefunc<T1, T2, T3>) {}

  void call(){ _somefunc(_ichi, _ni, _san); }

private:
  boost::any _ichi, _ni, _san;
  // adjust to your need
  typedef void (*func_type)(boost::any&, boost::any&, boost::any&);
  func_type _somefunc;

  template<class T1, class T2, class T3>
  void somefunc(boost::any& a1, boost::any& a2, boost::any& a3){
    // access any objects with 'boost::any_cast<TN>(aN)'
  }
};
Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397