C ++生成唯一的类型ID

时间:2019-10-10 20:24:42

标签: c++ templates unique id

我想为我想要的每种类型生成一个唯一的类型ID。 对于每个编译,此ID 不必不必相同-对于我指定的每种新类型都必须唯一。 我已经想出了两种解决方案。 这是第一个:

    template<typename T>
    struct TTypeIdentifier
    {
    private:

        static const T* const Identifier;

    public:

        static constexpr const T* const * GetIdentifier()
        {
            return &Identifier;
        }
    };

    template<typename T>
    const T* const TTypeIdentifier<T>::Identifier = nullptr;

这有效:

struct TestType : public TTypeIdentifier<TestType>
{

};

struct TestType2 : public TTypeIdentifier<TestType2>
{

};

int main()
{
    std::cout << TestType::GetIdentifier() << std::endl;
    std::cout << TestType2::GetIdentifier() << std::endl;

    return 0;
}

可能的输出为:
00007FF6862E2220
00007FF6862E2228

这是我想出的第二个解决方案:

    struct SCounter
    {
    private:
        template<typename T>
        friend struct TTypeIdentifier;

        static inline size_t Counter { 0 };
    };

    template<typename T>
    struct TTypeIdentifier : private SCounter
    {
    public:

        static constexpr size_t GetIdentifier()
        {
            static const size_t Identifier = SCounter::Counter++;
            return Identifier;
        }
    };

用法如下:

struct TestType : public TTypeIdentifier<TestType>
{

};

struct TestType2 : public TTypeIdentifier<TestType2>
{

};

int main()
{
    std::cout << TestType::GetIdentifier() << std::endl;
    std::cout << TestType2::GetIdentifier() << std::endl;

    return 0;
}

那里的输出:
0
1

如果您能给我一些建议,那哪种方法更优雅,哪种方法更少,那将非常好。 如果您有更好的解决方案可以提供,那就很好了。

提前谢谢

2 个答案:

答案 0 :(得分:1)

除非禁用了RTTI,否则typeidstd::type_index是获取类型的唯一ID的最可靠方法。考虑使用它,因为除非为整个项目明确禁用,否则您已经为之付出了全部代价。


如果您坚持使用自己的解决方案,那么我会说第一个更好,因为第二个不编译也不起作用。

那是因为这一行:

static const size_t Identifier = SCounter::Counter++;

首先,您不能在constexpr函数中包含静态数据,其次,您不能使用Counter本身不是的constexpr


第一个解决方案可以进一步改进。拥有一个指向T的指针的想法,在64位系统上占用8个字节,因此您可以拥有一个较小的数据,仅占用1个字节:

template<typename T>
struct TTypeIdentifier {
    static constexpr void const* GetIdentifier()
    {
        return &Identifier;
    }

private:
    struct id_t {};
    static constexpr id_t Identifier = id_t{};
};

使用id_t比空指针小得多。

这里唯一的缺点是您不能具有可预测的值,并且它们不是算术值。如果不使用std::less或标准库提供的其他功能对象,则无法比较它们。任何其他比较器都无法使用。

答案 1 :(得分:0)

您的第一个解决方案既更快又更小。它的GetIdentifier()方法不执行递增操作,而仅执行return。它还仅分配一个静态变量(用于指针),而另一个分配两个静态变量。由于size_t的大小至少等于指针的大小,因此第二个解决方案的分配量是指针的两倍。我再喜欢第一个。