简体   繁体   中英

C++ static const string in header c++11

I'm wanting to write a class that provides limited RTTI information.

Now what I want is something like this

template<typename T>
struct isGameComponent
{
   public:
   static_assert(false,"If a non-specialized version is created we have problems");
}

template<>
struct isGameComponent<Transform>
{
  public:
  static const char* COMPONENT_TYPE_NAME = "Transform";
  static const uint32_t COMPONENT_TYPE_ID = HashString("Transform"); //constexpr 
};

//Do this a lot more

I get a compile time error though saying I can't initialize the string as it is not a literal type. I was wanting to keep this lib header only. Is that impossible?

To keep the module as header only you have several options:

  • inline functions that return the values.
  • the templated constant trick.
  • C++11 constexpr keyword.

Example of inline functions:

template<typename T>
struct IsGameComponent;

template<>
struct IsGameComponent<Transform>
{
    static
    auto componenTypeName()
        -> const char*
    { return "Transform"; }

    static
    auto componentTypeId()
        -> uint32_t
    {
        static uint32_t const theId = hashString("Transform");
        return the_id;
    }
};

Example of the templated constant trick:

template<typename T>
struct IsGameComponent;

template< class Dummy_ >
struct C_IsGameComponent_Transform
{
    static char const* const componentTypeName;
    static uint32_t const componentTypeId;
};

template< class D >
char const* const C_IsGameComponent_Transform<D>::componentTypeName = "Transform";

template< class D >
uint32_t const C_IsGameComponent_Transform<D>::componentTypeId  = hashString( "Transform" );

template<>
struct IsGameComponent<Transform>
    : C_IsGameComponent_Transform<void>
{
    // Constants available here.
};

Example of C++11 constexpr (this requires that hashString is a constexpr function):

template<typename T>
struct IsGameComponent;

template< class Dummy_ >
struct C_IsGameComponent_Transform
{
    static char const* constexpr componentTypeName = "Transform";
    static uint32_t constexpr componentTypeId = hashString( "Transform" );
};

With this solution you can't take the address of any of these constants.


Disclaimer: none of the code above has been near any C++ compiler.

Define those static members out of the class declaration:

const char *isGameComponent<Transform>::COMPONENT_TYPE_NAME = "Transform";

const uint32_t isGameComponent<Transform>::COMPONENT_TYPE_ID = HashString("...");

If you put these definitions in the header file, then you will have multiple statics in every translation unit which may cause some issues. If you put them in a cpp file the you have one and it is recommended.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM