質問

Context

I oftenly use UUID implementation of Boost library to identify derived classes. To do so I usually use the following :
In the declaration file :

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

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

In the implementation file :

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

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


Question

I would like to know if it is possible to assign a value to the UUID in the declaration file.


Ideas

At first, I thought it was possible because Boost implementation is POD. Therefore I tried several ways to assign a value directly in the header using aggregate initializers (see boost documentation for an example of non static aggregate initializers) :

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

Unfortunately, it failed at compilation (the compiler can only initialize static const integral type).

Have you any suggestions to solve this issue, preferably using the Boost implementation of UUIDs ?

役に立ちましたか?

解決

The easiest way to define a non-integral constant as a class member in a header file is to wrap it in a function, like this:

typedef whatever Uuid;

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

If you want it as an actual constant, not a function, then you can use a little templating trick, like so:

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>
{};

With C++11 you can use constexpr, like this:

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

but, although a test of that compiles fine with no linker warnings with g++ 4.7.1, it's so new that I'm not sure if the standard's One Definition Rule actually supports it, or whether, with such definition in multiple translation units, I'm into Undefined Behavior.

So, if you want to do the constexpr, perhaps ask a separate question about the ODR.

As an alternative you can wait for the C++2040 standard and then just write

inline static Uuid const uuid = ...;

It is food for thought that, as shown, this hypothetical future feature can be emulated even in C++98, i.e. that all that's needed is already implemented by compiler and linker, and has been since the first standard. And yet, that that simple feature is lacking in the language. I believe that it's due to a kind of haphazard historical language evolution.

Anyway, I'd go for the simple function wrapper shown first. :-)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top