Question

Suppose I have a list of type list<boost::any> that has some type in it that is unknown. Now suppose I want to apply some operation to the elements in the list that is polymorphic. In this case, consider the + operator. Suppose that I know that the list will always contain a homogenous set of objects that support operator+, and I want to get the result of applying operator+ (the "sum" in one sense) between each element of the list into a new boost::any. Something like this:

boost::any sum(list<boost::any> lst) {
    // return lst[0]+lst[1]+lst[2] etc
}

Without enumerating all possible types that could support operator+, is there a way to do this? I'm extremely open to crazy ideas.

(I really do have an ok reason for doing this... I'm implementing an interpreter)

Was it helpful?

Solution

You could use boost::variant instead if you know the range of possible types in the list.

I don't see how you can do this without a mesh of operator+ functions to handle every possible combination of contained types, or regular runtime polymorphism.

What is the concrete type you wish to see in the final boost::any output, I wonder?

btw if you are implementing an interpreter, check out Boost.Spirit which might illuminate your design problem here.

OTHER TIPS

C++ matches functions (and operators are merely fancy functions that have an additional infix syntax) by their types, not by their names, at compile-time. (Rather than checking at run-time whether the objects involved support the requested operation.)
The only exception to that I can think of is virtual functions. If the types were polymorphic, you could use any of the workarounds for missing multi-methods (double dispatch). But since they can be anything, I don't think you can do this.

If you have a limited set of types, template-meta programming might help the generate functions implementing addition. But if the number of types involved were limited, you'd probably use boost::variant.

(IME saying this means that, in very short time, someone comes along and proves me wrong.)

No. Not with boost::any nor with boost::variant (doesn't qualify your, "Without enumerating all possible types that could support operator+," requirement).

What you need to do is make your own. The concept behind boost::any is quite simple. If you look at the documentation they have a link to an article explaining the technique (it's basically the handle/body idiom with polymorphism). All you need to do is decide what interface your various objects must have and write the 'any' interface and it's impl accordingly. Something resembling something like so:

struct my_any
{
  template < typename T >
  my_any(T const& t) : pimpl(new impl<T>(t)) {}
  ...
  some_type get_some_type() const;
   ...
private:
  struct impl_base
  {
    ....
    virtual some_type get_some_type() const = 0;
  };
  template < typename T >
  struct impl : impl_base
  {
    some_type get_some_type() const { return t.get_some_type(); }
    impl(T const& t_var) : t(t_var) {}
    ....
  };
  boost::scoped_ptr<impl_base> pimpl;
};

some_type operator+ (my_any const& a, my_any const& b)
{
  return a.get_some_type() + b.get_some_type();
}

It's hard to imagine what operator+ would do on generic types so I made something up that makes a small amount of sense to me. You'll of course need to change to your needs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top