gpt4 book ai didi

c++ - c++17 中的双向静态值映射

转载 作者:行者123 更新时间:2023-11-30 03:12:54 26 4
gpt4 key购买 nike

我想在 C++17 中高效地双向映射一些不同类型的值(仅对极少数值进行 1:1 映射)。例如考虑映射枚举值和整数,尽管该问题也适用于其他类型。目前,我是这样做的:

#include <optional>

enum class ExampleEnum { A, B, C, D, E };

class MyMapping {
public:
std::optional<int> enumToInt(ExampleEnum v) {
switch(v) {
case ExampleEnum::A:
return 1;
case ExampleEnum::B:
return 5;
case ExampleEnum::D:
return 42;
}
return std::nullopt;
}

std::optional<ExampleEnum> intToEnum(int v) {
switch(v) {
case 1:
return ExampleEnum::A;
case 5:
return ExampleEnum::B;
case 42:
return ExampleEnum::D;
}
return std::nullopt;
}
};

这有一个明显的缺点,就是所有的东西都要写两次,忘记更新其中一个函数会导致不一致。有没有更好的方法?

我需要:

  • 一致性。在映射和反向映射中不应该有不同的语义。
  • 编译时定义。映射的值是预先知道的,并且不会在运行时更改。
  • 运行时查找。在编译时不知道将查找哪些值,甚至可能根本不包含映射(而是返回一个空的可选值)。

我想要:

  • 没有额外的内存分配
  • 与双开关法性能基本相同
  • 使映射定义易于扩展的实现(即将来添加更多值或将其应用于其他类型)

最佳答案

我尝试了非常天真和简单的实现。 https://godbolt.org/z/MtcHw8

#include <optional>
enum class ExampleEnum { A, B, C, D, E };


template<typename Enum, int N>
struct Mapping
{
Enum keys[N];
int values[N];

constexpr std::optional<Enum> at(int x) const noexcept
{
for(int i = 0; i < N; i++)
if(values[i] == x) return keys[i];
return std::nullopt;
}

constexpr std::optional<int> at(Enum x) const noexcept
{
for(int i = 0; i < N; i++)
if(keys[i] == x) return values[i];
return std::nullopt;
}
};

constexpr Mapping<ExampleEnum, 3> mapping{{ExampleEnum::A, ExampleEnum::B, ExampleEnum::D},
{111, 222, 333}};

int main()
{
int x = rand(); // Force runtime implementation
auto optEnum = mapping.at(x);
if(optEnum.has_value())
return *mapping.at(ExampleEnum::B); // Returns 222, (asm line 3) constexpr works

auto y = (ExampleEnum)rand(); // Force runtime implementation
auto optInt = mapping.at(y);
if(optInt.has_value())
return (int)*mapping.at(333); // Returns 3, constexpr works

return 0;
}

它利用循环展开来实现 int -> ExampleEnum 中的切换方法性能映射。

装配ExampleEnum -> int映射是相当模糊的,因为优化器利用了枚举值是有序的并且更喜欢跳转表而不是 if-else 的事实。实现。

反正接口(interface)不需要复制,创建constexpr就可以了具有两个数组的对象被送入构造。相同类型可以有多个映射。另外,enum类型是模板化的。

此外,它可以轻松扩展以支持两个 enum class而不仅仅是 enum - int .

我还创建了带有原始开关实现的片段以进行汇编比较: https://godbolt.org/z/CbEcnZ

附言。我相信语法 constexpr Mapping<ExampleEnum, 3> mapping可以使用适当的模板推导指南进行简化,但我还没有找到如何去做。

PPS。我选择了N最多 15 个,循环展开仍在进行:https://godbolt.org/z/-Cpmgm

关于c++ - c++17 中的双向静态值映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59147517/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com