Search code examples
c++templatesc++03default-template-argument

How to specify a pointer-value template argument that defaults to NULL, in C++03?


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.


Solution

  • 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];
    };
    

    Demo

    You can put null in an anonymous namespace, although clang warns about it (I'm not sure why).

    namespace {
    const char * null[0];
    }