Создание уникального идентификатора путем объединения разных типов - PullRequest
0 голосов
/ 09 июля 2020

Я хочу создать уникальный идентификатор, «комбинируя» типы. Порядок типов ввода не имеет значения, и ввод одной и той же комбинации типов всегда должен возвращать один и тот же идентификатор (в той же среде выполнения). Я хочу использовать это в системе компонентов сущности для определения комбинаций компонентов.

Идея, которая почти выполняет свою работу:

    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

Это вернет уникальный идентификатор, но не позаботится о порядке. Может быть, это можно исправить, как-то упорядочив типы в функции CreateArchetype() с помощью некоторого «varadi c template sorting magi c», но мне не удалось этого сделать, возможно ли это или есть еще какие-то варианты?

1 Ответ

0 голосов
/ 16 июля 2020

Что ж, может быть способ сделать "Variadi c template sorting magi c", но если вам не нужно, чтобы идентификатор был доступен во время компиляции или для сортировки, вы можете просто использовать std :: type_info :: hash_code для каждого подтипа выполните некоторую не причудливую коммутативную операцию (например, сумму) и используйте этот результат в качестве идентификатора.

Однако учтите, что не гарантируется, что этот результат будет уникальным, и вы можете использовать имена этих типов, отсортировать и объединить результат, а затем sh it.

Я отредактировал ваш код, чтобы показать пример наивный подход с использованием суммы.

#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;
}
...