CZauX
CZauX

Reputation: 109

True dynamic vector typing

Is there a standard way of changing types inside of containers like std::vector? An example of this would be having:

std::vector<std::string> v;

v.insert("hi");

then changing the type up somehow and adding:

v.insert(1);

Very similiar to how interpreter languages are able to have multiple types in a list/array

I know vectors don't natively do that, however I'm lost on how to get around it without using 3rd party libraries like boost, and even with that I don't have a direction.

I created an example code to show off a kind of key-value data approach. It does work, however the (non-working) commented part in the middle is the idea that I was trying to implement.

#include <iostream>
#include <iterator>
#include <vector>
#include <map>
#include <string>
#include <typeinfo>

using namespace std;

int main()
{
    typedef std::map<std::string, std::string> map_type;
    typedef std::vector<map_type> vector_type;
    typedef std::map<std::string, map_type> map_keyobj_type;
    vector_type stack;
    vector_type::iterator it = stack.begin();

    //First map
    map_type stringmap;
    stringmap.insert(map_type::value_type("I'm a string", "Also a String"));
    it = stack.insert(it, stringmap);

    //Second wanted map, example code of what is wanted
    /*
    map_keyobj_type secondlayer;
    map_type secondlayervalue;
    secondlayervalue.insert(map_type::value_type("String from inside map",     "That too string"));
    secondlayer.insert(map_keyobj_type::value_type("List", secondlayervalue));
    stack.insert(it, secondlayer);
    */

    map_type stringmap2;
    stringmap2.insert(map_type::value_type("String after map map", "Also string"));
    it = stack.insert(it, stringmap2);


    //prints stack, only supports map_type
    //Iterates backwards to get top-down input correct.
    for (int i = stack.size()-1; i > -1; --i)
    {
        //Print map_type
        if (typeid(stack[i]).name() == typeid(map_type).name())
        {
            for (map_type::const_iterator ite = stack[i].begin(); ite != stack[i].end(); ++ite)
            {
                cout << ite->first << " : " << ite->second << "\n";
            }
        }
    }

    //return 0;
}

Upvotes: 0

Views: 93

Answers (2)

Zan Lynx
Zan Lynx

Reputation: 54325

You can use boost::any, the trick is you need to know what type you saved in order to get it out. This is also quite inefficient, if you care, because it saves a couple of pointers and your integer in place of just an integer.

You can use a discriminated union. That's a struct containing an enum and a union. The enum tells your code what type is saved in the union.

You mentioned interpreted languages. Most of them use the discriminated union method. Look at PyObject in Python or Perl's SV.

Upvotes: 1

p.i.g.
p.i.g.

Reputation: 2985

I'm not sure that this is the best solution but you could try using QVariant for this purpose. If you can't use Qt maybe you should implement your own class for this purpose.

Upvotes: 0

Related Questions