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++?
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.
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.
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.
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.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With