【问题标题】:Generic comparison operator for structs结构的通用比较运算符
【发布时间】:2019-11-26 00:16:20
【问题描述】:

在我的许多单元测试中,我需要比较只有数据成员的简单结构的内容:

struct Object {
  int start;
  int stop;
  std::string message;
}

现在,如果我想写这样的东西:

CHECK(object1==object2);

我总是要执行:

bool operator==(const Object& lhs, const Object& rhs) {
   return lhs.start==rhs.start && lhs.stop==rhs.stop && lhs.message=rhs.message;
}

编写所有这些比较函数变得乏味,但也容易出错。试想一下,如果我给 Object 添加一个新的数据成员,但是比较运算符不会更新,会发生什么。

然后我想起了我在 Haskell 中的知识和神奇的 deriving(Eq) 指令,它只是免费生成一个理智的比较函数。

如何,我可以在 C++ 中导出类似的东西吗?

幸运的是,我发现 C++17 带有一个通用的 operator==,并且每个结构都应该可以通过 std::make_tuple 轻松转换为 std::tuple

于是我大胆尝试了以下方法:

#include <tuple>
#include <iostream>
#include <tuple>

template<typename T>
bool operator==(const T& lhs, const T& rhs)
{
    auto leftTuple = std::make_tuple(lhs);
    auto rightTuple = std::make_tuple(rhs);

    return leftTuple==rightTuple;
}

struct Object
{
    std::string s;
    int i;
    double d;
};

int main(int arg, char** args)
{
    std::cout << (Object{ "H",1,2. } == Object{ "H",1,2. }) << std::endl;
    std::cout << (Object{ "A",2,3. } ==  Object{ "H",1,2. }) << std::endl;
    return EXIT_SUCCESS;
}

但是,不幸的是它无法编译,我真的不知道为什么。 Clang 告诉我:

main.cpp:11:18: error: use of overloaded operator '==' is ambiguous (with operand types
      'std::tuple<Object>' and 'std::tuple<Object>')
        return leftTuple==rightTuple;

我可以修复这个编译错误以获得我想要的行为吗?

【问题讨论】:

  • 你真的需要这个结构吗?你可以只使用一个元组吗?

标签: c++ c++17 stdtuple


【解决方案1】:

不,因为比较元组返回到比较元组的元素,所以leftTuple == rightTuple 尝试比较两个Objects,这是不可能的。

每个结构都应该可以通过std::make_tuple轻松转换为std::tuple

不,你只会得到一个带有一个元素的 tuple,结构体。

诀窍是使用std::tie:

std::tie(lhs.mem1, lhs.mem2) == std::tie(rhs.mem1, rhs.mem2)

但这与您的原始解决方案存在相同的问题。不幸的是,C++17 没有任何工具可以避免这个问题你可以写一个宏:)。但在 C++20 中,您将能够做到:

struct Object
{
    std::string s;
    int i;
    double d;
    bool operator==(const Object &) const = default;
};

这将为Object生成正确的比较运算符。

【讨论】:

  • 谢谢。我对std::make_tuple 能做什么有误解。
  • 看来,我正在寻找 std::make_from_tuple 的反面以使其工作。
  • @Aleph0 是的,你需要像create_tuple_from 这样的东西,但不幸的是,如果没有反射,这是不可能的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 2021-11-07
  • 1970-01-01
  • 2021-10-02
  • 2011-08-10
  • 2013-04-28
  • 1970-01-01
相关资源
最近更新 更多