【问题标题】:How can I use a custom type as key for a map in C++?如何在 C++ 中使用自定义类型作为映射的键?
【发布时间】:2010-10-28 17:17:32
【问题描述】:

我正在尝试将自定义类型指定为 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 之外没有任何改变。为什么我的第一个代码不起作用?

【问题讨论】:

    标签: c++ struct key operator-overloading stdmap


    【解决方案1】:

    其他答案已经解决了您的问题,但我想提供一个替代解决方案。由于C++11,您可以使用lambda expression 而不是为您的struct 定义operator&lt;。 (您的地图不需要operator&gt;。)向地图的构造函数提供 lambda 表达式具有一定的优势:

    • 我发现 lambda 表达式的声明比运算符更简单且不易出错。
    • 如果您无法修改要存储在地图中的struct,此方法特别有用。
    • 您可以为使用struct 作为关键字的不同地图提供不同的比较功能。
    • 您仍然可以对operator&lt; 进行不同的定义并将其用于不同的目的。

    因此,您可以将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;
    }
    

    输出:

    一个:1
    乙:2

    Code on Ideone

    【讨论】:

      【解决方案2】:

      我怀疑你需要

      bool operator<(const Foo& foo1) const;
      

      注意参数后面的<strong>const</strong>,这是为了使“你的”(比较中的左侧)对象保持不变。

      只需要一个运算符的原因是它足以实现所需的排序。要回答抽象问题“a 必须在 b 之前吗?”知道a是否小于b就足够了。

      【讨论】:

      • 你能说得更详细些吗?为什么只需要 operator?
      • 因为你可以从 operator 和 operator==。 (b &lt; a) 暗示 (a &gt; b),所以有 operator>。并且,(!(a &lt; b) &amp;&amp; !(b &lt; a)) 表示 a 不小于 b 也不大于 b,所以它必须等于 b。
      【解决方案3】:

      它可能正在寻找 const 成员运算符(无论正确的名称是什么)。 这有效(注意 const):

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

      编辑:从我的回答中删除了operator&gt;,因为它不需要(从问题中复制/粘贴),但它吸引了 cmets :)

      注意:我 100% 确定您需要那个 const,因为我编译了示例。

      【讨论】:

      • 有趣的 stackoverflow 显示了 10 分钟前的上一个答案,但是当我提交我的答案时,还没有任何答案......因此答案相同
      • 由于对象是常量,所以需要 const 函数。
      猜你喜欢
      • 2018-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-25
      • 1970-01-01
      • 2013-06-05
      相关资源
      最近更新 更多