OlivierB
OlivierB

Reputation: 323

Template specialization with static char* array member, instanciation in multiple units

I have a templated struct to store a static char* array, like this:

template<typename T>
struct EnumStrings {
    static const char* const data[];
};

And I would like to specialize it this way:

template<> const char* const EnumStrings<SomeType>::data[] =
    {"item1", "item2", "item3", "item4"};

If I place this instantiation in a header file, and this header file is included in multiple units, I get this linker error:

multiple definition of `EnumStrings<SomeType>::data'

Now, if I place this instantiation in the cpp file, other code using the data array cannot deduce its size with the sizeof operator, leading to the following error:

error: invalid application of ‘sizeof’ to incomplete type ‘const char* const []’

Because I need to be able to iterate over this array, so, I am stuck... Any suggestion? Of course, I would like not to have to specify the size of the array somewhere, but maybe that's the only possibility.

Upvotes: 1

Views: 422

Answers (3)

Blaz Bratanic
Blaz Bratanic

Reputation: 2279

You can put the struct declaration and definition of the data array specialization in an anonymous namespace. Struct will then have internal linkage which should prevent multiple definition errors.

namespace {
template<typename T>
struct EnumStrings {
    static const char* const data[];
};
template<> const char* const EnumStrings<int>::data[] =
    {"item1", "item2", "item3", "item4"};
}

Upvotes: 0

Constructor
Constructor

Reputation: 7473

You should divide declaration and definition of data array specialization. Put this in your header file:

template<typename T>
struct EnumStrings {
    static const char* const data[];
};

// declaration of `data` array specialization
template<> const char* const EnumStrings<SomeType>::data[4];

And this in your cpp file:

// definition of `data` array specialization
template<> const char* const EnumStrings<SomeType>::data[] =
    {"item1", "item2", "item3", "item4"};

Upvotes: 1

Jarod42
Jarod42

Reputation: 217275

in C++11 following works:

// In header:

class SomeType;
template<typename T> struct EnumStrings;

template<>
struct EnumStrings<SomeType> {
    static constexpr
    const char* const data[] =
        {"item1", "item2", "item3", "item4"};
};

// in cpp, if address of data is taken.

constexpr
const char* const EnumStrings<SomeType>::data[];

Upvotes: 1

Related Questions