0

我想通过“组合”类型来创建一个唯一的 id。输入类型的顺序无关紧要,输入相同的类型组合应始终返回相同的 id(在相同的运行时)。我想在实体组件系统中使用它来识别组件的组合。

一个几乎可以完成工作的想法:

    class Archetype
    {
    public:
        template <typename... Types>
        static uint32_t CreateArchetype()
        {
            return GetArchetypeIndex<Types...>();
        }
 
    private:
        template <typename... Types>
        static uint32_t GetArchetypeIndex()
        {
            static uint32_t index = GetNewArchetypeIndex();
            return index;
        }

        static uint32_t GetNewArchetypeIndex()
        {
            static uint32_t lastID = 0u;
            return ++lastID;
        }
    };
int main()
{
    std::cout << Archetype::CreateArchetype<uint16_t, uint32_t, int, bool>() << std::endl;
    std::cout << Archetype::CreateArchetype<uint16_t, uint32_t, int, bool>() << std::endl;

    // Same Types but different order
    std::cout << Archetype::CreateArchetype<int, bool, uint16_t, uint32_t>() << std::endl;
    std::cout << Archetype::CreateArchetype<int, bool, uint16_t, uint32_t>() << std::endl;
}

Output: 1, 1, 2, 2 Goal: 1, 1, 1, 1

这将返回一个唯一的 id,但它确实关心订单。也许这可以通过某种CreateArchetype()“可变模板排序魔法”以某种方式对函数中的类型进行排序来解决,但我还没有设法做到这一点,有可能还是有其他选择?

4

2 回答 2

0

对我来说,最简单的解决方案是为每个密集包装的组件类型提供唯一索引,即使用位集作为唯一 ID。前任:

// Order doesn't matter.
std::bitset<total_num_types> ent_id = (1ull << uint16_t_idx) |
                                      (1ull << uint32_t_idx) |
                                      (1ull << int_idx) |
                                      (1ull << bool_idx);

可以把它放在一个不错的可变参数函数模板后面。

于 2020-10-17T11:42:04.480 回答
0

好吧,可能有一种方法可以做“可变模板排序魔术”,但是如果您不需要在编译时使用 ID,也不需要对其进行排序,您可以对每个使用std::type_info::hash_code子类型执行一些非花哨的交换操作(如求和),并将此结果用作 id。

但是,请考虑到此结果不能保证是唯一的,您可能希望使用这些类型的名称,对结果进行排序和连接,然后对其进行哈希处理。

我编辑了您的代码,以显示使用总和的天真方法的示例。

#include <iostream>
#include <valarray>
#include <typeinfo>


    class Archetype
    {
    public:
        template <typename... Types>
        static uint32_t CreateArchetype()
        {
            return GetArchetypeIndex<Types...>();
        }

    private:
        template <typename... Types>
        static uint32_t GetArchetypeIndex()
        {
            std::valarray<size_t> a = { typeid(Types).hash_code()... };
            return a.sum();
            //static uint32_t index = GetNewArchetypeIndex();
            //return index;
        }

        static uint32_t GetNewArchetypeIndex()
        {
            static uint32_t lastID = 0u;
            return ++lastID;
        }
    };

int main()
{
    std::cout << Archetype::CreateArchetype<uint16_t, uint32_t, int, bool>() << std::endl;
    std::cout << Archetype::CreateArchetype<uint16_t, uint32_t, int, bool>() << std::endl;

    // Same Types but different order
    std::cout << Archetype::CreateArchetype<int, bool, uint16_t, uint32_t>() << std::endl;
    std::cout << Archetype::CreateArchetype<int, bool, uint16_t, uint32_t>() << std::endl;
}
于 2020-07-16T11:56:38.547 回答