Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
141 views
in Technique[技术] by (71.8m points)

using objects of two or more data types as key for c++ map, OOP

I have a class that contains a map. Earlier, there were two maps, one with char key and one with string key. I created a class that contains enum and union and two constructors, one from char and one from string, overloaded comparison operator and used that class as key.

But I keep wondering. could this have been solved with clever use of inheritance instead?

edit:

My class is something along the lines:

class A
{
    enum B
    {
        Ax, Ay
    } b;
    union C
    {
        X x;
        Y y;
    } c;
 public:
    A(X x) : b(Ax), c(x) {}
    A(Y y) : b(Ay), c(y) {}
    bool operator<(A& rhs)
    {
        if(this->b == rhs.b)
        {
            if(this->b == Ax) return this->c.x < b.c.x;
            if(this->b == Ay) reutrn this->c.y < b.c.y;
        }
        // if the "type" is different, I assume values are different
        // and all I need is any strong ordering, actual order doesn't matter
        return this->b < rhs.b;
    }
};

Later on I can use it fe. like that:

class Q
{
    // ...
public:
    Q(vector<A> v)
    {
        // don't worry about this code, I haven't figured out how c++11 for each
        // works exactly yet, but it's not important, I can do that myself
        for each (auto a in v)
        {
            // ...
        }
    }
};

Now using curly brackets I can initialize Q with various A, and I can create distinct A from char or string.

My class, Aaccomplished this by containing union for the actual data required to compare keys of one type, and enum used to compare keys of different types. Basic inheritance tree with virtual base class and two subclasses would result in every instance containing the same amount of information - different internal variables would take role of the union, and different actual classes would take the role of the enum. But I just can't come up with a way to do it properly without breaking any important principles.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Why not use boost::variant or std::variant once the latter becomes available in your compiler?

It feels like the most natural solution to the problem and makes the code very readable:

#include <boost/variant.hpp>

#include <string>
#include <map>
#include <iostream>

int main()
{
    using Key = boost::variant<char, std::string>;
    using Value = int; // whatever
    std::map<Key, Value> map;
    map['A'] = 1;
    map["B"] = 2;
    map["A"] = 3;

    for (auto&& key_value : map)
    {
        std::cout << key_value.first << " => " << key_value.second << '
';
    }
}

Output:

A => 1
A => 3
B => 2

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...