gpt4 book ai didi

c++ - 支持相等比较的类的 constexpr ID

转载 作者:太空狗 更新时间:2023-10-29 22:59:23 24 4
gpt4 key购买 nike

我需要创建一个独特的 constexpr我的 C++ 类的 ID。进一步的要求是这些 ID 应该具有可比性(如果它们可以与 >< 进行比较就更好了。

想到一个简单的解决方案:

template <typename T>
struct IDMaker {
static int i;
static constexpr void * id = &i;
}

这种方法的问题在于以下内容无法在 constexpr 中编译上下文:

IDMaker<int>::id == IDMaker<double>::id;

看来 idconstexpr但它的比较不是。我对此进行了一些试验,基本上您可以用这个 id 做任何有用的事情。在 constexpr 内语境。 (编辑:这是 GCC 5.3 中的一个错误,根据评论中的 dyp,clang 没有提示这个。这是 GCC 错误吗?还是 clang 过于宽容?)

为了提供一点上下文,我需要这个才能使用 constexpr用于元编程的函数,以便我可以在运行时重用相同的逻辑。例如,我希望能够编写一个函数,它接受两个类型的列表并返回一个数组,其中包含第二个列表中与第一个列表中的元素相匹配的元素的索引。如果我可以获得类的 ID,我可以轻松地将其实现为 constexpr接收两个类型 ID 数组的函数。除了重用 constexpr在运行时运行,我希望这也能加快我的编译时间。

我实际上有某种解决方案,但它涉及一些宏观魔法;本质上,我使用宏将类和命名空间的名称反射(reflect)为 constexpr const char * name(){return #NewType;}。我还可以访问类命名空间的反射类并获取其名称。我最后写了一个 constexpr哈希函数:

constexpr size_t hash(const char *str) {
size_t result{0};
for(size_t i =0; str[i]!=0; ++i) {
...
}
return result;
}

通过这个函数,我可以散列一个类的完整名称并获得一个 constexpr size_t , 它有效。不过,这种方法有两个问题:

1) 当我有 1000 个类时,我的编译时间会变得多糟糕?你能推荐一个快速的哈希函数吗?2) 我怎样才能避免散列冲突,或者至少在冲突发生时得到一个早期错误?

最佳答案

要在编译时为您的类生成一个 ID,您可以使用指向函数的指针。我将它实现为一个模板元函数,该函数返回一个指向函数的指针并将一个类型作为参数:

template<typename T>
void id_gen(){}

using type_id_t = void(*)(void);

template<typename T>
constexpr type_id_t type_id = &id_gen<T>;

由于函数 id_gen 的每个实例都有不同的地址,我们可以将其用作唯一标识符!

然后,你可以为你的类做一些语法糖:

template<typename Crtp>
struct Identified {
static constexpr type_id_t ID = type_id<Crtp>;
};

现在要识别您的类,您只需使用继承:

struct A : Identified<A> {};
struct B : Identified<B> {};

该方案的优势:

  • 没有碰撞
  • 非常快的编译时间
  • 易于在 std::map 中使用

此解决方案的缺点:

  • ID 的生成只是编译时的
  • 你无法预测这些值

关于c++ - 支持相等比较的类的 constexpr ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36983179/

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