I'm reading Meyers' book on modern c++, where I find a code snippet might be useful:
template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (&) [N]) noexcept {
return N;
}
This function deduces N for us as a compile-time constant. So I want to apply it in my code:
template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (&) [N]) noexcept {
return N;
}
template <typename T>
class A {
public:
const static char* names[];
};
template<typename T>
const char* A<T>::names[] = {"foo", "bar"};
template<>
const char* A<bool>::names[] = {"foo","bar", "foobar"};
If put in one file it works perfectly fine, arraySize(A<int>::names) is 2 and arraySize(A<bool>::names) is 3.
But when used in larger project requiring separate .h and .cpp, the problem comes:
If put the declaration of the specified version of
A<bool>::names[]in a.cpp, the code compiles(and links) but the compiler can't see it when deducingarraySize(), soarraySize(A<bool>::names)is deduced to2.If put the declaration of
A<bool>::names[]in a.h, of course, we get a "duplicate symbol" link error.
So how can I make arraySize(A<bool>::names) correctly deduced to 3?
You're using a
constexprfunctions so you're using a C++11 (or newer) compiler.So, if your
class Acontains onlynames(otherwise you can create a base class only fornames), you can declare itstatic constexprand (specializing the class) you can intialize it in the body class (in the header) and define it outside the body (in a cpp file, if you need) without initializiang it.And, if I uderstand correctly, starting from C++17, the outside of the class definition is no more necessary.
The following is an example
--- EDIT ---
The OP write
I add a modified example where
namesis inserted in a simple template base struct (namesB, base-for-names), containing onlynames.This permit the specialization only for the simple
namesBand a development, only one time, for a complexclass A.