C++ How to create a heterogeneous container

2019-02-07 04:55发布

问题:

I need to store a series of data-points in the form of (name, value), where the value could take different types.

I am trying to use a class template for each data-point. Then for each data-point I see, I want to create a new object and push it back into a vector. For each new type, I need to create a new class from the template first. But I can not store the objects created in any vector, since vectors expect the same type for all entries. The types I need to store can not be fitted in a inheritance hierarchy. They are unrelated. Also there can be more types created in future, and I do not want to change the storage service for each new type. Is there a way to create a heterogeneous container to store these entries? Thank you!

回答1:

The boost library has probably what you're looking for (boost::any). You can roll your own using a wrapped pointer approach if you cannot use boost...



回答2:

boost::any has already been recommended, however it's for anything, so you can't expect much from it.

If you know the various types ahead of time, you're better using boost::variant.

typedef boost::variant<Foo, Bar, Joe> variant_type;

struct Print: boost::static_visitor<>
{
  void operator()(Foo const& f) const { f.print(std::cout); }

  template <class T>
  void operator()(T const& t) const { std::cout << t << '\n'; }
};

void func(variant_type const& v) // not template
{
  boost::apply_visitor(Print(), v); // compile-time checking
                                    // that all types are handled
}


回答3:

The problem with containers like this is that when you want to access something in the container, you have to determine its type and then cast it to the actual type somehow. This is ugly, inefficient and error-prone, which is why the #1 choice in C++ is to use inheritance, unless you have a very good reason not to - something I've never actually come across in my C++ career.



回答4:

I was thinking that you could just have a Pair(type, void*) and write your own pop function that casts the void* depending upon the type describe in the pair and then shove these into whatever container catches your eye.