std::映射使用用户定义的类型作为键

时间:2021-01-03 16:32:12

I'm wondering why I can't use STL maps with user-defined classes. When I compile the code below, I get this cryptic error message. What does it mean? Also, why is it only happening with user-defined types? (primitive types are okay when it is used for the key)

我想知道为什么我不能在用户定义的类中使用STL映射。当我编译下面的代码时,我得到了这个神秘的错误消息。这是什么意思?而且,为什么它只发生在用户定义的类型上?(当用于密钥时,基本类型是可以的)

C:\MinGW\bin..\lib\gcc\mingw32\3.4.5........\include\c++\3.4.5\bits\stl_function.h||In member function `bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = Class1]':|

C:\ MinGW \ bin . . \ lib \ gcc \ mingw32 \ 3.4.5 ........ c++ \包括\ \ 3.4.5 \ \ stl_function碎片。h| bb2在成员函数bool std:: <_Tp>::算子()(const _tp&const _tp&) const _tp&) const [with _Tp = Class1]':|

C:\MinGW\bin..\lib\gcc\mingw32\3.4.5........\include\c++\3.4.5\bits\stl_map.h|338|instantiated from `_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = Class1, _Tp = int, _Compare = std::less, _Alloc = std::allocator >]'|

C:\ MinGW \ bin . . \ lib \ gcc \ mingw32 \ 3.4.5 ........ c++ \包括\ \ 3.4.5 \ \ stl_map碎片。从' _tp&std::map<_Key, _Tp, _Compare, _Alloc>: operator[](const _Key&) [with _Key = Class1, _Tp = int, _Compare = std: less, _Alloc = std:::allocator >]

C:\Users\Admin\Documents\dev\sandbox\sandbox\sandbox.cpp|24|instantiated from here|

C:\Users\Admin\Documents\dev\sandbox\sandbox\sandbox.cpp | 24从这里| |实例化

C:\MinGW\bin..\lib\gcc\mingw32\3.4.5........\include\c++\3.4.5\bits\stl_function.h|227|error: no match for 'operator<' in '__x < __y'| ||=== Build finished: 1 errors, 0 warnings ===|

C:\ MinGW \ bin . . \ lib \ gcc \ mingw32 \ 3.4.5 ........ c++ \包括\ \ 3.4.5 \ \ stl_function碎片。h|227|错误:__x < __y'| ||===构建完成:1个错误,0个警告==|

#include <iostream>
#include <map>

using namespace std;

class Class1
{
public:
    Class1(int id);

private:
    int id;
};

Class1::Class1(int id): id(id)
{}

int main()
{
    Class1 c1(1);

    map< Class1 , int> c2int;
    c2int[c1] = 12;

    return 0;
}

5 个解决方案

#1


113  

You don't have to define operator< for your class, actually. You can also make a comparator function object class for it, and use that to specialize std::map. To extend your example:

实际上,您不必为类定义操作符<。您还可以为它创建一个comparator函数对象类,并使用它来专门化std:::map。延长你的例子:

struct Class1Compare
{
   bool operator() (const Class1& lhs, const Class1& rhs) const
   {
       return lhs.id < rhs.id;
   }
};

std::map<Class1, int, Class1Compare> c2int;

It just so happens that the default for the third template parameter of std::map is std::less, which will delegate to operator< defined for your class (and fail if there is none). But sometimes you want objects to be usable as map keys, but you do not actually have any meaningful comparison semantics, and so you don't want to confuse people by providing operator< on your class just for that. If that's the case, you can use the above trick.

碰巧std:::map的第三个模板参数的默认值是std::less,它将委托给为类定义的操作符<(如果没有的话将失败)。但是有时您希望对象作为映射键是可用的,但是实际上您没有任何有意义的比较语义,因此您不希望仅仅为其在类上提供操作符 <来迷惑人们。如果是这样,你可以使用上面的技巧。< p>

Yet another way to achieve the same is to specialize std::less:

另一种实现这一目标的方法是专门化std::less:

namespace std
{
    template<> struct less<Class1>
    {
       bool operator() (const Class1& lhs, const Class1& rhs) const
       {
           return lhs.id < rhs.id;
       }
    };
}

The advantage of this is that it will be picked by std::map "by default", and yet you do not expose operator< to client code otherwise.

这样做的好处是std::map“默认”会选择它,但是您不会将操作符 <暴露给客户端代码。< p>

#2


19  

By default std::map (and std::set) use operator< to determine sorting. Therefore, you need to define operator< on your class.

默认情况下,std::map(和std::set)使用运算符 <来确定排序。因此,您需要定义操作符<在您的类上。< p>

Two objects are deemed equivalent if !(a < b) && !(b < a).

如果!(a < b) & !(b < a)

If, for some reason, you'd like to use a different comparator, the third template argument of the map can be changed, to std::greater, for example.

如果出于某种原因,您希望使用另一个比较器,那么可以将映射的第三个模板参数更改为std::greater。

#3


11  

You need to define operator < for the Class1.

您需要为Class1定义操作符<。

Map needs to compare the values using operator < and hence you need to provide the same when user defined class are used as key.

Map需要使用operator <来比较值,因此在使用用户定义的类作为键时需要提供相同的值。< p>

class Class1
{
public:
    Class1(int id);

    bool operator <(const Class1& rhs) const
    {
        return id < rhs.id;
    }
private:
    int id;
};

#4


2  

Keys must be comparable, but you haven't defined a suitable operator< for your custom class.

键必须具有可比性,但是您还没有为自定义类定义合适的操作符<。

#5


2  

class key
{
    int m_value;
public:
    bool operator<(const key& src)const
    {
        return (this->m_value < src.m_value);
    }

};
int main()
{
    key key1;
    key key2;
    map<key,int> mymap;
    mymap.insert(pair<key,int>(key1,100));
    mymap.insert(pair<key,int>(key2,200));
    map<key,int>::iterator iter=mymap.begin();
    for(;iter!=mymap.end();++iter)
    {
        cout<<iter->second<<endl;
    }


}

#1


113  

You don't have to define operator< for your class, actually. You can also make a comparator function object class for it, and use that to specialize std::map. To extend your example:

实际上,您不必为类定义操作符<。您还可以为它创建一个comparator函数对象类,并使用它来专门化std:::map。延长你的例子:

struct Class1Compare
{
   bool operator() (const Class1& lhs, const Class1& rhs) const
   {
       return lhs.id < rhs.id;
   }
};

std::map<Class1, int, Class1Compare> c2int;

It just so happens that the default for the third template parameter of std::map is std::less, which will delegate to operator< defined for your class (and fail if there is none). But sometimes you want objects to be usable as map keys, but you do not actually have any meaningful comparison semantics, and so you don't want to confuse people by providing operator< on your class just for that. If that's the case, you can use the above trick.

碰巧std:::map的第三个模板参数的默认值是std::less,它将委托给为类定义的操作符<(如果没有的话将失败)。但是有时您希望对象作为映射键是可用的,但是实际上您没有任何有意义的比较语义,因此您不希望仅仅为其在类上提供操作符 <来迷惑人们。如果是这样,你可以使用上面的技巧。< p>

Yet another way to achieve the same is to specialize std::less:

另一种实现这一目标的方法是专门化std::less:

namespace std
{
    template<> struct less<Class1>
    {
       bool operator() (const Class1& lhs, const Class1& rhs) const
       {
           return lhs.id < rhs.id;
       }
    };
}

The advantage of this is that it will be picked by std::map "by default", and yet you do not expose operator< to client code otherwise.

这样做的好处是std::map“默认”会选择它,但是您不会将操作符 <暴露给客户端代码。< p>

#2


19  

By default std::map (and std::set) use operator< to determine sorting. Therefore, you need to define operator< on your class.

默认情况下,std::map(和std::set)使用运算符 <来确定排序。因此,您需要定义操作符<在您的类上。< p>

Two objects are deemed equivalent if !(a < b) && !(b < a).

如果!(a < b) & !(b < a)

If, for some reason, you'd like to use a different comparator, the third template argument of the map can be changed, to std::greater, for example.

如果出于某种原因,您希望使用另一个比较器,那么可以将映射的第三个模板参数更改为std::greater。

#3


11  

You need to define operator < for the Class1.

您需要为Class1定义操作符<。

Map needs to compare the values using operator < and hence you need to provide the same when user defined class are used as key.

Map需要使用operator <来比较值,因此在使用用户定义的类作为键时需要提供相同的值。< p>

class Class1
{
public:
    Class1(int id);

    bool operator <(const Class1& rhs) const
    {
        return id < rhs.id;
    }
private:
    int id;
};

#4


2  

Keys must be comparable, but you haven't defined a suitable operator< for your custom class.

键必须具有可比性,但是您还没有为自定义类定义合适的操作符<。

#5


2  

class key
{
    int m_value;
public:
    bool operator<(const key& src)const
    {
        return (this->m_value < src.m_value);
    }

};
int main()
{
    key key1;
    key key2;
    map<key,int> mymap;
    mymap.insert(pair<key,int>(key1,100));
    mymap.insert(pair<key,int>(key2,200));
    map<key,int>::iterator iter=mymap.begin();
    for(;iter!=mymap.end();++iter)
    {
        cout<<iter->second<<endl;
    }


}