std :: maps以用户定义的类型作为键

unk*_*own 60 c++ containers dictionary stl stdmap

我想知道为什么我不能将STL映射用于用户定义的类.当我编译下面的代码时,我得到这个神秘的错误消息.这是什么意思?此外,为什么它只发生在用户定义的类型?(当用于密钥时,原始类型是可以的)

C:\ MinGW\bin ..\lib\gcc\mingw32\3.4.5 ........\include\c ++\3.4.5\bits\stl_function.h ||在成员函数`bool std :: less <_Tp> :: operator()(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 |从`_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 |从这里实例化|

C:\ MinGW\bin ..\lib\gcc\mingw32\3.4.5 ........\include\c ++\3.4.5\bits\stl_function.h | 227 |错误:不匹配'运算符<'in'__ 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;
}
Run Code Online (Sandbox Code Playgroud)

Pav*_*aev 132

你不具备定义operator<为类,其实.您也可以为它创建一个比较器函数对象类,并使用它来进行特化std::map.扩展你的例子:

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

std::map<Class1, int, Class1Compare> c2int;
Run Code Online (Sandbox Code Playgroud)

只是碰巧第三个模板参数的默认值std::mapstd::less,它将委托给operator<你的类定义(如果没有,则失败).但有时你希望对象可以用作地图键,但你实际上并没有任何有意义的比较语义,所以你不想通过operator<在你的课堂上提供这些来混淆别人.如果是这种情况,您可以使用上述技巧.

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

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

这样做的好处是它将被std::map"默认" 选中,但是你不会暴露operator<给客户端代码.

  • 我建议在这两个函数中添加一个const关键字. (5认同)

GMa*_*ckG 23

默认情况下std::map(和std::set)用于operator<确定排序.因此,您需要operator<在您的班级上定义.

两个对象被认为是等同的 if !(a < b) && !(b < a).

例如,如果由于某种原因,您想要使用不同的比较器,map则可以更改第三个模板参数std::greater.

  • 事实上,您可以将比较器更改为大多数任何双参数函数. (3认同)

aJ.*_*aJ. 14

您需要operator <为Class1 定义.

Map需要使用operator <来比较值,因此当用户定义的类用作键时,您需要提供相同的值.

class Class1
{
public:
    Class1(int id);

    bool operator <(const Class1& rhs) const
    {
        return id < rhs.id;
    }
private:
    int id;
};
Run Code Online (Sandbox Code Playgroud)


小智 6

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;
    }


}
Run Code Online (Sandbox Code Playgroud)

  • 欢迎来到 StackOverflow!请在您的答案中添加一些解释。 (6认同)

Meh*_*dad 5

如果您只需添加,您的示例可以在 C++20 中运行

auto operator<=>(Class1 const &) const = default;
Run Code Online (Sandbox Code Playgroud)

到你的班级。