I'm working on a little bit-chord class, and I want to add to it a feature where you can pass in an array of strings as a template-parameter, so that the class can print out its current state in a human-friendly format. A sketch of the class looks like this:
#include <iostream>
template <unsigned int NumBits, const char * optLabelArray[NumBits]=0> class MyBitChordClass
{
public:
MyBitChordClass() {}
static const char * GetBitLabel(unsigned int which) {return ((optLabelArray != 0)&&(which < NumBits)) ? optLabelArray[which] : "???";}
bool _bits[NumBits];
};
enum {
FRUIT_APPLE,
FRUIT_BANANA,
FRUIT_CHERRY,
NUM_FRUITS
};
const char * _fruitLabels[] = {
"Apple",
"Banana",
"Cherry"
};
int main(int, char **)
{
MyBitChordClass<NUM_FRUITS> unlabelledFruits;
MyBitChordClass<NUM_FRUITS, _fruitLabels> labelledFruits;
std::cout << labelledFruits.GetBitLabel(FRUIT_APPLE) << std::endl;
return 0;
}
This works great under C++11 and later, if I change the default value of the optLabelArray
template-argument to nullptr
instead of 0
.
However, I'd like to get it working under C++03 also, and under C++03 when I try to compile the above program, I get this error (from Apple's clang 15.0.0):
Mac-mini:~ jaf$ g++ foo.cpp
foo.cpp:3:69: error: non-type template argument does not refer to any declaration
template <unsigned int NumBits, const char * optLabelArray[NumBits]=0> class MyBitChordClass
^
foo.cpp:28:30: note: while checking a default template argument used here
MyBitChordClass<NUM_FRUITS> unlabelledFruits;
~~~~~~~~~~~~~~~~~~~~~~~~~~^
foo.cpp:3:46: note: template parameter is declared here
template <unsigned int NumBits, const char * optLabelArray[NumBits]=0> class MyBitChordClass
^
1 error generated.
My question is, how can I get this code to compile under C++03? I tried doing some explicit casting to const char *[]
, as suggested here, but that didn't seem to help.
The only way I see this working is by giving that default value a name:
const char * null[0];
template <unsigned int NumBits, const char * optLabelArray[NumBits]=null> class MyBitChordClass
{
public:
MyBitChordClass() {}
static const char * GetBitLabel(unsigned int which) {return ((optLabelArray != null)&&(which < NumBits)) ? optLabelArray[which] : "???";}
bool _bits[NumBits];
};
You can put null
in an anonymous namespace, although clang warns about it (I'm not sure why).
namespace {
const char * null[0];
}