Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing a list of arbitrary objects in C++

In Java, you can have a List of Objects. You can add objects of multiple types, then retrieve them, check their type, and perform the appropriate action for that type.
For example: (apologies if the code isn't exactly correct, I'm going from memory)

List<Object> list = new LinkedList<Object>();

list.add("Hello World!");
list.add(7);
list.add(true);

for (object o : list)
{
    if (o instanceof int)
        ; // Do stuff if it's an int
    else if (o instanceof String)
        ; // Do stuff if it's a string
    else if (o instanceof boolean)
        ; // Do stuff if it's a boolean
}

What's the best way to replicate this behavior in C++?

like image 260
Whatsit Avatar asked Mar 03 '09 18:03

Whatsit


People also ask

Can a list store different types?

A list can only hold the items of the datatype of its declared datatype. We can declare a list of datatype Object and store items of different datatype. But after accessing the item we do need to cast to the right datatype.

Can you store class objects in an array?

Yes, since objects are also considered as datatypes (reference) in Java, you can create an array of the type of a particular class and, populate it with instances of that class.

Can we store different data types in list in C#?

We can use an ArrayList class that is present in the System. Collections namespace,. Using it we can store different types because the ArrayList class operates on the object type.

Can we store different data types in vector C++?

On the other hand, The standard container like vector and list that comes with C++ is already generic. The main problem with them is they can be the container for any data type but they must be of the same type. In other words, they cannot contain multiple data types.


1 Answers

boost::variant is similar to dirkgently's suggestion of boost::any, but supports the Visitor pattern, meaning it's easier to add type-specific code later. Also, it allocates values on the stack rather than using dynamic allocation, leading to slightly more efficient code.

EDIT: As litb points out in the comments, using variant instead of any means you can only hold values from one of a prespecified list of types. This is often a strength, though it might be a weakness in the asker's case.

Here is an example (not using the Visitor pattern though):

#include <vector>
#include <string>
#include <boost/variant.hpp>

using namespace std;
using namespace boost;

...

vector<variant<int, string, bool> > v;

for (int i = 0; i < v.size(); ++i) {
    if (int* pi = get<int>(v[i])) {
        // Do stuff with *pi
    } else if (string* si = get<string>(v[i])) {
        // Do stuff with *si
    } else if (bool* bi = get<bool>(v[i])) {
        // Do stuff with *bi
    }
}

(And yes, you should technically use vector<T>::size_type instead of int for i's type, and you should technically use vector<T>::iterator instead anyway, but I'm trying to keep it simple.)

like image 179
j_random_hacker Avatar answered Oct 13 '22 01:10

j_random_hacker