I use a compile-time counter in some applications, and it is really useful. Yesterday I wanted to compile a program with gcc (I was using msvc before), and the behavior of the counter changed in templated classes (it is not working anymore in template classes).
The overly simplified code:
// Maximum value the counter can hold
#define MAX_COUNT 64
// Used to store a number as the size of the structure
template<unsigned int n> struct Count { bool data[n]; };
// Used to overload functions while automatically selecting the
// right one based on the counter value (see following code)
template<int n> struct cn : public cn<n-1> {};
template<> struct cn<0> {};
struct Test
{
#define COUNT \
((sizeof(f(cn<MAX_COUNT + 1>())) / sizeof(bool)) - 1)
static Count<1> f(cn<1>);
/*
f(cn<65>()) will 'call' f(cn<1>) and return a Count<1> with size 1
-> count = 0;
*/
static const int a = COUNT;
static Count<COUNT + 2> f(cn<COUNT + 2>); // increase counter
/*
now Count<2> f(cn<2>) is defined, so:
f(cn<65>()) will 'call' f(cn<2>) and return a Count<2> with size 2
-> count = 1;
*/
static const int b = COUNT;
};
The idea is to use function overloading, and if you test the above code it will work perfectly (a == 0
and b == 1
).
However, if the struct Test
is made template (by just adding template<something>
before its declaration for example, no need to use the template parameter), the counter breaks and I end up with a == b == 1
. It also implies that it is impossible to increment the counter in these conditions.
So here are my questions :
- what template rules are at work here ?
- why that specific behavior ?
- do you have an idea of a work-around for the counter to actually work ?
Note: I would like a C++03 answer for compatibility with old compilers (even if I'm curious to know if rules for that specific case changed for C++11)
EDIT: Some outputs:
VC2010:
Templated a = 0 b = 1
-
Templated a = 1 b = 1
Clang 3.4 (thanks to dyp):
Templated a = 0 b = 1
EDIT 2
GCC seems to take Count
as a dependent name, as observable here (thanks to dyp). I posted a bug report in gcc bugzilla here.