English 中文(简体)
可以用大小不一的钥匙使用STL地图
原标题:Can a STL map be used with keys of varying sizes

能否用一个STL地图绘制不同规模的钥匙?

我没有这方面的法典。 如果能够做到这一点,我仍要指出这一点,因此我的问题。 (一) 在不可能解决的问题上花费太多时间的类型。 我希望从你的智慧中学习。

我正在研究一个基本上有两个要点的桌子。 数字型钥匙和特定次要钥匙。

例如,第一级的关键是:

enum key_type {
  E_ERROR = 0,
  E_INT   = 1,
  E_CHAR  = 2,
  E_STR   = 3,
}; // Yes I know you don t HAVE to specify the values for the enumeration

然后,二级钥匙取决于关键类型。 <编码>E_INT的次要关键是:E_CHAR是个性格。

Key: E_INT
2ndary Key Examples: 1, 2, 3, 4

Key: E_CHAR
2ndary Key Examples:  a ,  b ,  c ,  d 

Key: E_STR
2ndary Key Examples: "abc", "xyz", "pdq", "jrr"

我的第一个反应是使这成为一系列地图点。 第一级钥匙被用作阵列中的指数。 阵列指数在支持二级关键类型的地图上标明。

+--------+
| E_INT  |------------------------------>+------------------+
+--------+                               | MAP with INT key |
| E_CHAR |---------------               +------------------+
+--------+                
| E_STR  |------          ---->+-------------------+
+--------+                      | MAP with CHAR key |
                                +-------------------+
                   
                    ------>+------------------+
                            | MAP with STR key |
                            +------------------+

页: 1 我可以得出以上结论,但我认为,我可以把这两个要点结合起来,并有一个单一的地图,加上一个处理合并钥匙的习惯<代码>sort(<>>>/代码>算法。

我完全想到这一点吗? 如果不是要说,你是否就如何着手这样做提出建议?

在基类为某种方法提供纯虚拟功能的钥匙上,作为我头部的顶部,需要为这些关键类别留下一个继承的类别,然后继承了使用<代码>E_INT、E_CHARE_STR的钥匙。 然后,我将使用基数关键类别作为地图的关键。

评论?


<EDIT 页: 1

我正在尝试一些解决办法,以及我最初的想法。 我仍然有问题。 我确实在提及,这可能为我不同的钥匙 do。


<EDIT 8/16/2010

在下文的答复部分加上一个答案,表明已采用编码解决办法一。

最佳回答
问题回答

虽然提出了许多解决办法...... 他们中没有任何人认为:

typedef boost::variant<int,char,std::string> key_type;

typedef std::map<key_type, value_type> map_type;

页: 1 <代码>boost:variant依自然按类型和类型(在类型相同时)按其所携带的数值(如果可以比较)先后顺序排列。

我挑战任何人找到更简单的解决办法......

我认为,你的做法与习俗钥匙的关系是正确的。

尽管如此,如果你能够避免把N地图与一个具有习俗钥匙的地图相隔,那么我会说,因为N地图是微薄的,而且是迅速的。 你们甚至能够打上地图,只是躲藏在另一类的后面。

EDIT:您的习惯比较器也应简明扼要。 你可以首先严格按顺序排列,然后对具有相同价值的关键人物(CHAR、INT、可疑交易等)来说,你应比照价值。 这将保证按以下顺序排列:地图。

你们需要把两个关键点总结为一个单一目标。 你的新班子也需要可比。 指称:

struct myKey
{
  int key1;
  std::string key2;

  bool operator<(const myKey&) const;
}; 

关键1和关键2是(智能)点。 一旦物体(如我的凯伊)通过“斜线”进行对比,即可在地图上使用。

如果能提高: 与一个比较的操作者如。 http://www.sgi.com/tech/stl/Map.html。 只要经营者能够命令,你就应当能够使用多种类型作为关键。 如果能提高: 他们将占用比钥匙本身更多的空间,但此处所示解决办法的其余部分也将带来间接费用。

你们是否必须把所有名单整理在一起? 如果是的话,那么,如果你试图接触一些要素,你的做法就会是痛苦的。

简单地建立工会类型和对工会的比较功能,是解决问题的 way脚石:

typedef struct IntRecord {
    key_type key;
    int record;
};

typedef struct CharRecord {
    key_type key;
    char record;
};

typedef struct StrRecord {
    key_type key;
    const char * record;
};

typedef struct Base {
    key_type key;
};
typedef union Record {
    Base b;
    IntRecord i;
    CharRecord c;
    StrRecord s;
};

现在,您的比较功能可以看一看每个记录,看看应使用哪类。

您可针对实施<代码>和>的钥匙实施一个分类;操作员,例如(未测试):

struct UnionMapKey {
    int key_type;
    union {
        Error *err; // maybe pointer because complex types can t be in C unions
        int i;
        char c;
        string *s; // pointer because complex types can t be in C unions
    };
    UnionMapKey(const string &stringContent) { key_type = E_STR; s = new string(stringContent); }
    // other constructor overrides
    bool operator<(const UnionMapKey &rhs) {
        if (key_type != rhs.key_type) return key_type < rhs.key_type;
        if (key_type == E_ERROR) return err < rhs.err;
        // etc.
    }
    ~UnionMapKey() {
        if (key_type == E_STR) delete s;
    }
};

也许你还需要一份复印件,但我认为你会这样做。 一旦你 iron倒了小块,这就会成为地图钥匙。 诚然,如果你为你工作,你的各种计划解决方案可能更加简单。

www.un.org/Depts/DGACM/index_spanish.htm 解决办法一


共识是可以这样做。 http://www.artima.com/cppsource/type_erasure.html” rel=“nofollow noreferer” 字幕: 概念,以及上述其他建议。 我现在谈一些事情。 地图钥匙必须是对多形态关键物体有点的物体。

我试图把基标作为关键类别,但当地图制作其关键人物的拷贝时,它就认为它只是复制基类。

因此,I naively转向点(key_base_c*)。 然而,这只是比较点。 甚至使用了我的分类。

在阅读 型时代sure。 我调整了我的分辨率,将其放在了<条码> 倍_key_c。 转交<代码>和t;,=strIdx()的物体:key_base_c 点击器I在座。

在撰写了两门衍生课程之后,我很快看到,这使我们成为模板,我的解决办法很快就被落实。

我怀疑有更好的执行方式,但这里是我迄今为止:

#include <map>
#include <sstream>
#include <iostream>
#include <utility>



//
// list of types to act as the primary key. The primary key dicatates the
// format of the secondary key.
//
enum e_types {
    E_ERROR  = 0,
    E_INT    = 1,
    E_CHAR   = 2,
    E_STR    = 3,
};





// Base class for the multi-key.
class key_base_c {

public:

    key_base_c (enum e_types    key_type) :
        key1(key_type)
        {};


    virtual ~key_base_c(void) {};


    virtual std::string strIdx (void) const {
        std::stringstream    ss_idx;

        ss_idx << key1;
        return (ss_idx.str());
    }


    virtual bool operator< (const key_base_c    &b) const {
        return (key_base_c::operator<(&b));
    }


    virtual bool operator< (const key_base_c    *p) const {
        return (key1 < p->key1);
    }


    virtual bool operator== (const key_base_c    &b) const {
        return (key_base_c::operator==(&b));
    }


    virtual bool operator== (const key_base_c    *p) const {
        return (key1 == p->key1);
    }


protected:

    e_types    key1;   // the primary key

};





// template    policy_key_c
//
// EVENT_TYPE_VAL    -  select the enumerated value to use for key1 s value
//
// KEY2_TYPE         -  select the class to use for the second key. For built
//                      in types they use their default < and == operators,
//                      If a private custom type is specified then it must
//                      have its own < and == operators specified
//
template <enum e_types    EVENT_TYPE_VAL,
          class           KEY2_TYPE>
class policy_key_c : public key_base_c
{
public:

    policy_key_c (KEY2_TYPE    key_value) :
        key_base_c(EVENT_TYPE_VAL),
        key2(key_value)
        {};


    virtual ~policy_key_c(void) {};


    // return the index as a string.
    virtual std::string strIdx (void) const {
        std::stringstream    ss_idx;

        ss_idx << key_base_c::strIdx() << "." << key2;
        return (ss_idx.str());
    }


    //
    // operator <
    //
    virtual bool operator< (const key_base_c    &b) const {
        return (operator<(&b));
    }


    virtual bool operator< (const key_base_c    *p) const {

        // if the primary key is less then it s less, don t check 2ndary
        if (key_base_c::operator<(p)) {
            return (true);
        }


        // if not less then it s >=, check if equal, if it s not equal then it
        // must be greater
        if (!(key_base_c::operator==(p))) {
            return (false);
        }


        // primary keys are equal, so now check the 2ndary key. Since the
        // primary keys are equal then that means this is either a key_base_c
        // object or its a policy_key_c object.
        const policy_key_c    *p_other = dynamic_cast<const policy_key_c*>(p);


        // if NULL then it was a key_base_c, and has no secondary key, so it is
        // lexigraphically smaller than us, ergo we are not smaller than it.
        if (!p_other) {
            return (false);
        }

        return (key2 < p_other->key2);
    }



    //
    // operator ==
    //
    virtual bool operator== (const key_base_c    &b) const {
        return(operator==(&b));
    }


    virtual bool operator== (const key_base_c    *p) const {

        // if the primary key isn t equal, then we re not equal
        if (!(key_base_c::operator==(p))) {
            return (false);
        }


        // primary key is equal, so now check the secondary key. Since the
        // primary keys are equal, then that means this is eitehr a key_base_c
        // object or its a policy_key_c object.
        const policy_key_c    *p_other = dynamic_cast<const policy_key_c*>(p);

        // if NULL then it was a key_base_c
        if (!p_other) {
            // why? If the LHS is a key_base_c it doesn t go any deeper than
            // the base. Hence we don t either.
            return (true);
        }

        return (key2 == p_other->key2);
  }


protected:

    KEY2_TYPE    key2;    // The secondary key.

};



class multi_key_c {
public:
    multi_key_c (key_base_c    *p) :
        p_key(p)
        {};


    ~multi_key_c(void) {};


    bool operator< (const multi_key_c    &mk) const {
        return (p_key->operator<(mk.p_key));
    }


    bool operator== (const multi_key_c    &mk) const {
        return (p_key->operator==(mk.p_key));
    }


    std::string strIdx (void) const {
        return (p_key->strIdx());
    }

protected:
    key_base_c    *p_key;
};







// DO_TEST(x, op, y)
//    x, y: can be any derived key type
//    op  : The operation to do < or ==
//
//    Prints the operation being done along with the results of the operation
//    For example:
//        DO_TEST(a, <, b)
//    will print:
//        a < b: <results>
//
//    where <results> are the results of the operation  a < b 
#define DO_TEST(x, op, y, expect)                                             
{                                                                             
    bool    retval = x op y;                                                  
    std::cout << #x " " #op " " #y ": " << retval                             
              << " = " << ((retval == expect) ? "pass" : "----FAIL") << "
"; 
}





template <class C>
void
print_them (C              **pp_c,
            int            count,
            std::string    s_type)
{
    int    idx;

    std::cout << "
" << count << " keys for " << s_type << "
";

    for (idx = 0 ; idx < count; ++idx) {
        std::cout << "    " << (*pp_c)->strIdx() << "
";
        pp_c++;
    }
}






int
main (void)
{
    std::cout << "
BASE
";

    key_base_c    base_error(E_ERROR), base_int(E_INT), base_char(E_CHAR);
    key_base_c    base_str(E_STR);

    key_base_c    *key_base_array[] = {
        &base_error, &base_int, &base_char, &base_str
    };


    print_them(key_base_array,
               (sizeof(key_base_array) / sizeof(key_base_array[0])),
               "key_base_c");

    DO_TEST(base_error, < , base_error,  false);
    DO_TEST(base_error, < , base_int,    true);
    DO_TEST(base_int,   < , base_char,   true);
    DO_TEST(base_char,  < , base_str,    true);

    std::cout << "
";
    DO_TEST(base_error, ==, base_error,  true);
    DO_TEST(base_int,   ==, base_int,    true);
    DO_TEST(base_char,  ==, base_char,   true);
    DO_TEST(base_str,   ==, base_str,    true);

    std::cout << "
";
    DO_TEST(base_error, ==, base_int,    false);
    DO_TEST(base_int,   ==, base_char,   false);
    DO_TEST(base_char,  ==, base_str,    false);




    // INT
    //
    typedef policy_key_c<E_INT, int>    key_int_2;

    key_int_2    i1(1), i2(2), i3(3), i4(4);
    key_int_2    *key_int2_array[] = {
        &i1, &i2, &i3, &i4,
    };


    print_them(key_int2_array,
               (sizeof(key_int2_array) / sizeof(key_int2_array[0])),
               "key_int_2");

    DO_TEST(base_int,     < , i1,          false);
    DO_TEST(i1,           < , base_int,    false);

    DO_TEST(i1,           < , base_char,   true);
    DO_TEST(base_char,    < , i1,          false);

    DO_TEST(i1,           ==, i1,          true);
    DO_TEST(i1,           ==, base_int,    true);
    DO_TEST(base_int,     ==, i1,          true);
    DO_TEST(i1,           ==, base_error,  false);
    DO_TEST(base_error,   ==, i1,          false);


    std::cout << "
";
    DO_TEST(i1,   < , i2, true);
    DO_TEST(i1,   < , i3, true);
    DO_TEST(i1,   < , i4, true);



    // CHAR
    typedef policy_key_c<E_CHAR, char>    key_char_c;


    key_char_c    c1( a ), c2( b ), c3( c ), c4( d );
    key_char_c    *key_char_array[] = {
        &c1, &c2, &c3, &c4,
    };

    print_them(key_char_array,
               (sizeof(key_char_array) / sizeof(key_char_array[0])),
               "key_char");


    DO_TEST(base_int,      < , c1,      true );
    DO_TEST(base_int,      ==, c1,      false);
    DO_TEST(base_char,     < , c1,      false);
    DO_TEST(base_char,     ==, c1,      true );
    DO_TEST(base_str,      < , c1,      false);
    DO_TEST(base_str,      ==, c1,      false);

    std::cout << "
";
    DO_TEST(c1,            < , c1,      false);
    DO_TEST(c1,            ==, c1,      true );
    DO_TEST(c1,            < , c2,      true );
    DO_TEST(c1,            ==, c2,      false);

    std::cout << "
";
    DO_TEST(c1,            ==, i1,      false);
    DO_TEST(i1,            ==, c1,      false);
    DO_TEST(c1,            < , i1,      false);
    DO_TEST(i1,            < , c1,      true );



    // STR
    typedef policy_key_c<E_STR, std::string>    key_str_c;


    key_str_c    s1("aaa"), s2("bbb"), s3("ccc"), s4("ddd");
    key_str_c    *key_str_array[] = {
        &s1, &s2, &s3, &s4
    };

    print_them(key_str_array,
               (sizeof(key_str_array) / sizeof(key_str_array[0])),
               "key_str");

    DO_TEST(base_int,     < , s1,         true );
    DO_TEST(base_char,    < , s1,         true );
    DO_TEST(base_str,     < , s1,         false);
    DO_TEST(base_str,     ==, s1,         true );
    DO_TEST(s1,           < , base_int,   false);
    DO_TEST(s1,           < , base_char,  false);
    DO_TEST(s1,           < , base_str,   false);
    DO_TEST(s1,           ==, base_str,   true);


    std::cout << "
";
    DO_TEST(s1,            < , s1,      false);
    DO_TEST(s1,            ==, s1,      true );
    DO_TEST(s1,            < , s2,      true );
    DO_TEST(s1,            ==, s2,      false);



    std::cout << "

NOW TESTING THE MAP

";

    typedef std::multimap<multi_key_c, std::string>    multiKeyMap;

    multiKeyMap    myMap;


    multi_key_c    k1(&i1),  k2(&i2),  k3(&i3),  k4(&i4);
    multi_key_c    k5(&c1),  k6(&c2),  k7(&c3),  k8(&c4);
    multi_key_c    k9(&s1),  k10(&s2), k11(&s3), k12(&s4);


    myMap.insert(std::make_pair(k1, "one"));
    myMap.insert(std::make_pair(k2, "two"));
    myMap.insert(std::make_pair(k3, "three"));
    myMap.insert(std::make_pair(k4, "four"));
    myMap.insert(std::make_pair(k1, "one.2"));
    myMap.insert(std::make_pair(k4, "four.2"));

    myMap.insert(std::make_pair(k5, "c1"));
    myMap.insert(std::make_pair(k5, "c1.2"));
    myMap.insert(std::make_pair(k6, "c2"));
    myMap.insert(std::make_pair(k6, "c2.2"));
    myMap.insert(std::make_pair(k7, "c3"));
    myMap.insert(std::make_pair(k8, "c4"));


    myMap.insert(std::make_pair(k9,  "s1"));
    myMap.insert(std::make_pair(k10, "s2"));
    myMap.insert(std::make_pair(k11, "s3"));
    myMap.insert(std::make_pair(k12, "s4"));
    myMap.insert(std::make_pair(k12, "s4.2"));
    myMap.insert(std::make_pair(k11, "s3.2"));
    myMap.insert(std::make_pair(k10, "s2.2"));
    myMap.insert(std::make_pair(k9,  "s1.2"));

    multiKeyMap::iterator    pos;

    for (pos = myMap.begin(); pos != myMap.end(); ++pos) {
        std::cout << pos->first.strIdx() << " : " << pos->second
                  <<"
";
    }


    return (0);
}

www.un.org/Depts/DGACM/index_spanish.htm 产出:

BASE

4 keys for key_base_c
    0
    1
    2
    3
base_error < base_error: 0 = pass
base_error < base_int: 1 = pass
base_int < base_char: 1 = pass
base_char < base_str: 1 = pass

base_error == base_error: 1 = pass
base_int == base_int: 1 = pass
base_char == base_char: 1 = pass
base_str == base_str: 1 = pass

base_error == base_int: 0 = pass
base_int == base_char: 0 = pass
base_char == base_str: 0 = pass

4 keys for key_int_2
    1.1
    1.2
    1.3
    1.4
base_int < i1: 0 = pass
i1 < base_int: 0 = pass
i1 < base_char: 1 = pass
base_char < i1: 0 = pass
i1 == i1: 1 = pass
i1 == base_int: 1 = pass
base_int == i1: 1 = pass
i1 == base_error: 0 = pass
base_error == i1: 0 = pass

i1 < i2: 1 = pass
i1 < i3: 1 = pass
i1 < i4: 1 = pass

4 keys for key_char
    2.a
    2.b
    2.c
    2.d
base_int < c1: 1 = pass
base_int == c1: 0 = pass
base_char < c1: 0 = pass
base_char == c1: 1 = pass
base_str < c1: 0 = pass
base_str == c1: 0 = pass

c1 < c1: 0 = pass
c1 == c1: 1 = pass
c1 < c2: 1 = pass
c1 == c2: 0 = pass

c1 == i1: 0 = pass
i1 == c1: 0 = pass
c1 < i1: 0 = pass
i1 < c1: 1 = pass

4 keys for key_str
    3.aaa
    3.bbb
    3.ccc
    3.ddd
base_int < s1: 1 = pass
base_char < s1: 1 = pass
base_str < s1: 0 = pass
base_str == s1: 1 = pass
s1 < base_int: 0 = pass
s1 < base_char: 0 = pass
s1 < base_str: 0 = pass
s1 == base_str: 1 = pass

s1 < s1: 0 = pass
s1 == s1: 1 = pass
s1 < s2: 1 = pass
s1 == s2: 0 = pass


NOW TESTING THE MAP

1.1 : one
1.1 : one.2
1.2 : two
1.3 : three
1.4 : four
1.4 : four.2
2.a : c1
2.a : c1.2
2.b : c2
2.b : c2.2
2.c : c3
2.d : c4
3.aaa : s1
3.aaa : s1.2
3.bbb : s2
3.bbb : s2.2
3.ccc : s3
3.ccc : s3.2
3.ddd : s4
3.ddd : s4.2




相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签