【问题标题】:std::find with two different typesstd::find 有两种不同的类型
【发布时间】:2017-06-13 07:11:30
【问题描述】:

我正在尝试将 std::find 与两种不同的类型一起使用,但提供了必要的布尔运算符。

class FooDetails
{
public:
    FooDetails(int size = 5)
    : m_size(size) { /* empty */ }
    bool operator<(const FooDetails& other) const { return m_size < other.m_size; }
    bool operator==(const FooDetails& other) const { return m_size == other.m_size; }
private:
    int m_size;
};

class Foo
{
public:
    Foo(int size)
    : m_details(size) { /* empty */}

    bool operator==(const Foo& other) const { return m_details == other.m_details; }
    bool operator==(const FooDetails& other) const {return m_details == other; }
    bool operator<(const Foo& other) const { return m_details < other.m_details; }
    bool operator<(const FooDetails& other) const { return m_details < other; }
    FooDetails m_details;
};

bool operator==(const FooDetails& lhs, const Foo& rhs) { return lhs == rhs.m_details; }
bool operator==(const Foo& lhs, const FooDetails& rhs) {return lhs.m_details == rhs; }
bool operator<(const FooDetails& lhs, const Foo& rhs) { return lhs < rhs.m_details; }
bool operator<(const Foo& lhs, const FooDetails& rhs) { return lhs.m_details < rhs; }

int main() {
    std::vector<Foo> haystack = { FooDetails(5), FooDetails(6), FooDetails(7) };

    FooDetails needle(6);
    std::find(haystack.begin(), haystack.end(), needle);
    return 0;
}

由于 std::find 使用 operator== 我希望这可以工作,因为提供了所有必要的功能。但是,这不会编译。为什么会这样,我该如何解决? 我知道我可以使用 std::find_if,但我认为这有点慢,即使不是,我也想知道为什么 std::find 不起作用。

【问题讨论】:

  • 那么究竟是什么的错误是什么?在哪一行。
  • 你有两次operator==,所以编译器不知道选择哪一个。注释掉一个就行了。下一个错误是初始化类型为Foo 的干草堆,类型为FooDetails

标签: c++ c++11 stl operator-overloading


【解决方案1】:

我已将您的代码更改为:

#include <algorithm>

class FooDetails
{
public:
    FooDetails(int size = 5)
    : m_size(size) { /* empty */ }
    bool operator<(const FooDetails& other) const { return m_size < other.m_size; }
    bool operator==(const FooDetails& other) const { return m_size == other.m_size; }
private:
    int m_size;
};

class Foo
{
public:
    Foo(int size)
    : m_details(size) { /* empty */}

    FooDetails m_details;
};

bool operator==(const FooDetails& lhs, const Foo& rhs) { return lhs == rhs.m_details; }
bool operator==(const Foo& lhs, const FooDetails& rhs) {return lhs.m_details == rhs; }
bool operator<(const FooDetails& lhs, const Foo& rhs) { return lhs < rhs.m_details; }
bool operator<(const Foo& lhs, const FooDetails& rhs) { return lhs.m_details < rhs; }

int main() {
    std::vector<Foo> haystack = { Foo(5), Foo(6), Foo(7) };

    FooDetails needle(6);
    std::find(haystack.begin(), haystack.end(), needle);
    return 0;
}

它成功编译。您的原始版本包含两个错误:

  1. 您尝试创建 std::vector&lt;Foo&gt; 并使用 std::initialization_list&lt;FooDetails&gt; 对其进行初始化。
  2. 您提供了太多比较运算符:免费版本和 Foo 结构的成员。所以在查找期间编译器抱怨它不知道选择哪一个。您应该只留下其中一个。

【讨论】:

  • 太好了,谢谢。向量的初始化是当然示例中的一个错字。我没有意识到我可以有太多的比较运算符。谢谢!
【解决方案2】:

Foo 类中没有这样的构造函数,它从 FooDetails 构造它。您需要定义以下内容,您的代码才能正常工作:

Foo(const FooDetails& d) : m_details(d) {}

【讨论】:

  • 我知道它会像这样工作,但我认为如果我只提供适当的比较运算符它也应该工作。因为使用构造函数解决方案,我假设每次搜索都会构造一个 Foo 对象,这应该会对性能产生影响,对吧?
  • 构造函数是从FooDetails 对象初始化std::vector&lt;Foo&gt; haystack 所必需的。 std::find 不会构造新的Foo 对象,因为您重载了Foo 和FooDetails 的比较运算符,因此编译器不需要将FooDetails 隐式转换为Foo 进行比较。跨度>
  • 是的,正如我所说,那只是一个错字。
猜你喜欢
  • 1970-01-01
  • 2014-12-09
  • 2020-06-24
  • 1970-01-01
  • 2018-11-25
  • 1970-01-01
  • 1970-01-01
  • 2015-06-22
相关资源
最近更新 更多