C++结构的自动比较器

标签 c++ c++11 struct comparison metaprogramming

有许多原始结构(数百个),用于在两个组件(例如播放器和服务器)之间传输数据。其中没有方法,只有原始数据。 任务是编写所有请求和答案,以便能够在没有服务器的情况下重播玩家场景(我们记住所有问题和所有答案,它们都是纯函数)。 所以任务是将这个结构放在没有比较器的映射中。现在我们使用memcmp,它允许不考虑这个结构的变化并且它是紧凑的,但是填充等问题太多。

是否有可能获得类似 getHashValue 或任何默认比较器的 smth 元编程? 状况: 1) 我不想为每个结构创建一个比较器。 2)如果添加或删除字段破坏了现有行为并需要修复,我希望出现错误。 3) 我不想更改带有结构定义的头文件。

结构的例子

struct A {
  int a;
  int b;
  c c;
}

bool operator<(const A& a1, const A& a2)
{
  if (a1.a != a2.a) return a1.a < a2.a;
  if (a1.b != a2.b) return a1.b < a2.b;
  if (a1.c != a2.c) return a1.c < a2.c;
  return false;
} 

我可以考虑使用其他语言来实现这个确切的部分(收集问题/答案),如果它不需要再次用该语言描述所有这些结构的话。

最佳答案

在 C++17 中,如果您愿意 (A) 在某处对每个结构中的元素数量进行硬编码,并且 (B) 为结构中元素的每个计数编写或生成代码,则可以实现此目的.

template<std::size_t N>
using size_k = std::integral_constant<std::size_t, N>;

template<class T>
auto auto_tie( size_k<0>, T&& t ) {
  return std::tie();
}
template<class T>
auto auto_tie( size_k<1>, T&& t ) {
  auto& [ x0 ] = std::forward<T>(t);
  return std::tie( x0 );
}
template<class T>
auto auto_tie( size_k<2>, T&& t ) {
  auto& [ x0, x1 ] = std::forward<T>(t);
  return std::tie( x0, x1 );
}
// etc

现在,在相关结构的命名空间中,写

struct foo {
  int x;
};
struct bar {
  int a, b;
};
size_k<1> elems( foo const& ) { return {}; }
size_k<2> elems( bar const& ) { return {}; }

一个 elems 函数返回 size_k 计算元素的数量。

现在在结构的命名空间中,写:

template<class T, class Size=decltype(elems(std::declval<T const&>()))>
bool operator<( T const& lhs, T const& rhs ) {
  return auto_tie( Size{}, lhs ) < auto_tie( Size{}, rhs );
}

你就完成了。

测试代码:

foo f0{1}, f1{2};
bar b0{1,2}, b1{-7, -3};

std::cout << (f0<f1) << (f1<f0) << (f0<f0) << "\n";
std::cout << (b0<b1) << (b1<b0) << (b0<b0) << "\n";

Live example .

比这更进一步将需要编写第 3 方工具或等待对 C++ 的反射扩展,可能在 C++20 或 23 中。

如果 elems 出错,我相信 auto_tie 中的结构化绑定(bind)代码应该会产生错误。

关于C++结构的自动比较器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44613310/

相关文章:

c++ - =default 和没有参数的空构造函数之间的区别?

c++ - 在 C++ 中连接字符串时令人困惑

c++ - 无法将库与 cmake 中的测试二进制文件链接

c++ - 如何使用 C++ 解析 vector 的路径

c++ - 英特尔 C++ 编译器是否有边界检查?

c++ - 向类添加复制构造函数

c++ - 为什么此代码片段适用于 C++17 而编译器在使用 C++11 时会报错?

c - 如何在运行时为结构数组赋值?

c++ - 包含字符串值的结构在使用动态内存分配创建后在分配时导致段错误

Swift 不能在结构内部使用任何变量