Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Heterogeneous array implementation

Tags:

c++

arrays

c

I would appreciate your help!

Which data structure is used to implement heterogeneous array in C or C++ ? The array may contain any standard data types like int,float, char, string etc...

like image 248
leader Avatar asked Feb 12 '23 15:02

leader


2 Answers

As ravi mentions, the appropriate data structure is called a tag-union (also called variant record). One way to implement it is this:

typedef union {
    int tag;
    struct {
        int tag;
        int val;
    } int_;
    struct {
        int tag;
        double val;
    } double_;
} object;

Then you can make an array of these.

object arr[5];

You use the tag field to indicate which union member is in use. Typically with an enum.

enum type { INT, DOUBLE };

Then set the tag when creating the object, and check the tag before accessing. This can be encapsulated by using constructor functions.

object new_int(int i){
    object ret;
    ret.tag = INT;
    ret.int_.val = i;
    return ret;
}

object new_double(double d){
    object ret;
    ret.tag = DOUBLE;
    ret.double_.val = d;
    return ret;
}

And you usually want to use a switch on the tag for accessing, writing a different case for each type.

void print_object(object x){
    switch(x.tag){
    case INT: printf("%d\n", x.int_.val); break;
    case DOUBLE: printf("%f\n", x.double_.val); break;
    }
}

Or in some circumstances, you may want to fold the array into a single type so it can be accessed without checking the tag each time.

for (i = 0; i < sizeof arr/sizeof*arr; i++)
    if (arr[i].tag == INT)
        arr[i] = new_double(arr[i].int_.val);
like image 160
luser droog Avatar answered Feb 15 '23 11:02

luser droog


There is no such array in c++ which can store elements of different types nor there is container in stl. Although there's one way to store different element in a container but condition is those types should be related through inheritance.

In C there's a concept called tagged union which can store different types giving tag as a means to specify which variable is actually there.

One more way to do this is using an array of void* pointers. Although that would be quite ugly C++. This would not be truly heterogeneous as you are using a type of pointer that any pointer can be cast into. It is similar to making a collection of base class type and then storing objects of derived classes.

This I got from Stroustrup article:-

If you need a heterogeneous container in C++, define a common interface for all the elements and make a container of those. For example:

class Io_obj { /* ... */ }; // the interface needed to take part in object I/O

vector<Io_obj*> vio;        // if you want to manage the pointers directly
vector< Handle<Io_obj> > v2;    // if you want a "smart pointer" to handle the objects

Apart from that Boost::Any can also be used:-

vector<Any> v;
like image 30
ravi Avatar answered Feb 15 '23 12:02

ravi