简体   繁体   中英

Storing attributes in a STL container?

Suppose I have a class called generic_pair of the form:

template < typename K, typename V >
struct generic_pair{
  K key;
  V value;
};

Now, the problem is I would like to be able to store a bunch of these generic_pairs in an STL container BUT not all < K, V > in the container will be of the same type. For example, some elements may be < int, int > whereas others may be < int , string > and so on. Question is how can we do this?

My first thought is to use "tags" to create a hierarchy of encapsulated types and declare the container with the generic type but actual elements with inherited types. For example,

struct base_type{
  typedef void type;
};

struct int_type: base_type{
  typedef int type;
}

struct string_type: base_type{
  typedef std::string type;
}

/// and so on establish a type hierarchy as necessary and then...

std::vector < generic_pair < base_type, base_type > > vec;

I bet there is a better, more correct way to do this? Any ideas, directions appreciated. If you have seen similar implementations or relevant tools/techniques in MPL or elsewhere that's helpful too. (I am trying to avoid macros)

You can use Boost.Variant if the set of types is determined in advance. If not, then Boost.Any might do the trick.

From your question and subsequent comments that clarify matters, the following would do what you're asking for:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>

// All class-template instantiations derive from this
struct AbstractPair
{
    virtual std::string serialize() const = 0;
};

template<typename K, typename V>
struct Pair : public AbstractPair
{
public:
    Pair(K key, V value) : key(key), value(value) {}

    std::string serialize() const
    {
        std::stringstream ss;
        ss << "Key: " << key << ", Value: " << value;
        return ss.str();
    }
    K key;
    V value;
};


int main()
{
    // Vector of pointers-to-abstract-base
    std::vector<AbstractPair *> v;

    // Create derived objects (instantiate class template)
    AbstractPair *p1 = new Pair<int,int>(5,10);
    AbstractPair *p2 = new Pair<float,std::string>(3.2f, "Hello");

    // Valid, and type-safe
    v.push_back(p1);
    v.push_back(p2);

    // Demonstrate polymorphism
    for(std::vector<AbstractPair *>::iterator it = v.begin(); it != v.end(); ++it)
    {
        std::cout << (*it)->serialize() << std::endl;
    }

    // Boilerplate cleanup
    delete p1;
    delete p2;
    return 0;
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM