【问题标题】:Define a static const Universal Unique Identifier (UUID)定义静态常量通用唯一标识符 (UUID)
【发布时间】:2025-12-21 02:05:11
【问题描述】:

上下文

我经常使用 Boost 库的 UUID 实现来识别派生类。 为此,我通常使用以下内容:
在声明文件中:

  #include "ClassA.h"
  #include <boost/uuid/uuid.hpp>

  class SubClass1 : public ClassA {
    public:
      static const boost::uuids::uuid classId; // 7feb24af-fc38-44de-bc38-04defc3804de
    ... 
  };

在实现文件中:

  #include "SubClass1.h"
  #include <boost/uuids/uuid_generator.h>

  const boost::uuids::uuid SubClass1 ::classId = boost::uuids::string_generator()("{7feb24af-fc38-44de-bc38-04defc3804de}");
  ...


问题

我想知道是否可以在声明文件中为 UUID 赋值。


想法

起初,我认为这是可能的,因为 Boost 实现是 POD。因此,我尝试了几种使用聚合初始化器直接在标头中分配值的方法(有关非静态聚合初始化器的示例,请参阅boost documentation):

  static const boost::uuids::uuid classId = { 0x7f, 0xeb, ... };

很遗憾,编译失败(编译器只能初始化静态常量整型)。

您有什么建议来解决这个问题,最好使用 UUID 的 Boost 实现?

【问题讨论】:

    标签: c++ uuid boost-uuid


    【解决方案1】:

    在头文件中将非整数常量定义为类成员的最简单方法是将其包装在函数中,如下所示:

    typedef whatever Uuid;
    
    class MyClass
    {
    public:
        static Uuid const& uuid()
        {
            Uuid const theValue = ...;
            return theValue;
        }
    };
    

    如果你希望它是一个实际的常量,而不是一个函数,那么你可以使用一些模板技巧,如下所示:

    template< class Dummy >
    class MyClass_constants
    {
    public:
        static Uuid const uuid;
    };
    
    template< class Dummy >
    Uuid const MyClass_constants<Dummy>::uuid = ...;
    
    class MyClass
        : public MyClass_constants<void>
    {};
    

    使用 C++11 你可以使用constexpr,像这样:

    class MyClass
    {
    public:
        static Uuid constexpr uuid = ...;
    };
    

    但是,尽管使用 g++ 4.7.1 的测试编译良好,没有链接器警告,但它太新了,我不确定标准的单一定义规则是否真的支持它,或者是否在多重翻译中使用这样的定义单位,我喜欢未定义的行为。

    所以,如果您想提交constexpr,或许可以单独问一个关于 ODR 的问题。

    作为替代方案,您可以等待 C++2040 标准,然后直接编写

    inline static Uuid const uuid = ...;
    

    值得深思的是,如图所示,即使在 C++98 中,这个假设的未来特性也可以模拟,即所有需要的东西都已经由编译器和链接器实现,并且已经被自第一个标准以来。然而,这种简单的功能在语言中是缺乏的。我相信这是由于某种偶然的历史语言演变。

    无论如何,我会选择首先显示的简单函数包装器。 :-)

    【讨论】:

    • 现在我必须做出选择!谢谢。