2

语境

我经常使用 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 文档):

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

不幸的是,它在编译时失败了(编译器只能初始化静态 const 整数类型)。

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

4

1 回答 1

2

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

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 中也可以模拟这个假设的未来特性,即编译器和链接器已经实现了所有需要的功能,并且从第一个标准开始就已经实现。然而,这种简单的功能在语言中是缺乏的。我相信这是由于一种偶然的历史语言演变。

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

于 2012-10-18T09:35:46.987 回答