81

ユーザー定義のクラスで 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|エラー: 'operator に一致しません<' 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;
}
4

8 に答える 8

168

実際、クラスを定義する必要はありません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;

の 3 番目のテンプレート パラメータのデフォルトが でstd::mapあり、クラスの defined にstd::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;
       }
    };
}

これの利点は、「デフォルトで」選択されることですが、それ以外の場合はクライアント コードにstd::map公開されません。operator<

于 2009-07-09T09:11:21.417 に答える
33

デフォルトではstd::map(およびstd::set) を使用operator<して並べ替えを決定します。operator<したがって、クラスで定義する必要があります。

2 つのオブジェクトは同等 if !(a < b) && !(b < a)と見なされます。

何らかの理由で別のコンパレータを使用したい場合は、 の 3 番目のテンプレート引数を、たとえばmapに変更できます。std::greater

于 2009-07-09T07:44:26.303 に答える
19

operator <Class1に対して定義する必要があります。

Map は演算子 < を使用して値を比較する必要があるため、ユーザー定義のクラスをキーとして使用する場合は同じものを提供する必要があります。

class Class1
{
public:
    Class1(int id);

    bool operator <(const Class1& rhs) const
    {
        return id < rhs.id;
    }
private:
    int id;
};
于 2009-07-09T07:44:23.853 に答える
4
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;
    }


}
于 2015-11-06T15:44:09.263 に答える
3

キーは比較可能でなければなりませんがoperator<、カスタム クラスに適した を定義していません。

于 2009-07-09T07:44:43.820 に答える