23

のキーとしてカスタムタイプを割り当てようとしていますstd::map。これが私がキーとして使用しているタイプです:

struct Foo
{
    Foo(std::string s) : foo_value(s){}

    bool operator<(const Foo& foo1) {   return foo_value < foo1.foo_value;  }

    bool operator>(const Foo& foo1) {   return foo_value > foo1.foo_value;  }
    
    std::string foo_value;
};

と一緒に使用するとstd::map、次のエラーが発生します。

error C2678: binary '<' : no operator found which takes a left-hand operand of type 'const Foo' (or there is no acceptable conversion) c:\program files\microsoft visual studio 8\vc\include\functional 143

を以下のものに変更するstructと、すべてが機能します。

struct Foo
{
    Foo(std::string s) : foo_value(s)   {}

    friend bool operator<(const Foo& foo,const Foo& foo1) { return foo.foo_value < foo1.foo_value;  }

    friend bool operator>(const Foo& foo,const Foo& foo1) { return foo.foo_value > foo1.foo_value;  }
    
    std::string foo_value;
};

オペレーターがfriendとしてオーバーロードされていることを除いて、何も変更されていません。最初のコードが機能しないのはなぜですか?

4

3 に答える 3

32

私はあなたが必要だと思う

bool operator<(const Foo& foo1) const;

const引数の後、これは「your」(比較の左側)オブジェクトを一定にするためのものであることに注意してください。

オペレーターが1人だけ必要な理由は、必要な順序付けを実装するだけで十分だからです。「aはbの前に来る必要がありますか?」という抽象的な質問に答えるために。aがbよりも小さいかどうかを知るだけで十分です。

于 2009-05-25T10:53:28.717 に答える
3

おそらくconstメンバー演算子を探しています(正しい名前が何であれ)。これは機能します(constに注意):

bool operator<(const Foo& foo1) const { return foo_value < foo1.foo_value;}

operator>編集:必要がなかったので私の答えから削除しました(質問からコピー/貼り付け)が、コメントを集めていました:)

注:例をコンパイルしたので、そのconstが必要であると100%確信しています。

于 2009-05-25T11:03:41.707 に答える
0

他の答えはすでにあなたの問題を解決していますが、私は別の解決策を提供したいと思います。C ++ 11以降では、を定義する代わりにラムダ式を使用できoperator<ますstruct。(operator>マップが機能するために必要ではありません。)マップのコンストラクターにラムダ式を提供することには、特定の利点があります。

  • ラムダ式の宣言は、演算子の宣言よりも単純でエラーが発生しにくいことがわかりました。
  • structこのアプローチは、マップに保存するものを変更できない場合に特に役立ちます。
  • キーとしてを使用するマップごとに、異なる比較機能を提供できますstruct
  • それでも、別の方法で定義operator<し、別の目的に使用することができます。

structその結果、次のように短くすることができます。

struct Foo {
    Foo(std::string s) : foo_value(s) {}
    std::string foo_value;
};

そして、マップは次のように定義できます。

int main() {
    auto comp = [](const Foo& f1, const Foo& f2) { return f1.foo_value < f2.foo_value; };
    std::map<Foo, int, decltype(comp)> m({ {Foo("b"), 2}, {Foo("a"), 1} }, comp);
    // Note: To create an empty map, use the next line instead of the previous one.
    // std::map<Foo, int, decltype(comp)> m(comp); 

    for (auto const &kv : m)
        std::cout << kv.first.foo_value << ": " << kv.second << std::endl;

    return 0;
}

出力:

a:1
b:2

Ideoneのコード

于 2020-08-03T13:46:13.797 に答える