From mboxrd@z Thu Jan 1 00:00:00 1970 From: Greg Chicares To: egcs Subject: Bug report Date: Mon, 14 Sep 1998 21:16:00 -0000 Message-id: <35FDD8B1.E46FD962@ibm.net> X-SW-Source: 1998-09/msg00472.html List-Id: // result of g++ -v // Reading specs from C:\MINGW32\LIB\GCC-LIB\i386-mingw32\egcs-2.90.27\specs // gcc version egcs-2.90.27 980315 (egcs-1.0.2 release) #include template class Factorial { public: enum {value = N * Factorial < N - (N == 0) ? N :(0::value }; }; int main() { Factorial<3> f3; cout << f3.value << endl; } // Result of compiling as // g++ bug00.cpp // bug00.cpp:14: parse error before `}' // bug00.cpp:14: missing ';' before right brace // bug00.cpp:15: parse error before `}' // bug00.cpp: In function `int main()': // bug00.cpp:19: `class Factorial<3>' has no member named `value' // Windows 95 OSR2, using MingW32 /* I inquired about this in comp.lang.c++.moderated and was told: > I'd expect this to compile. Will you please submit a bug > report to egcs-bugs@cygnus.com ? Here is an extract from my original post if that's helpful. >> // Expression template uses recursion, specialization >> // Instantiations evaluated completely at compile time >> template class Factorial { >> public: >> enum {value = N * Factorial::value}; >> }; >> // specilization for 1, ends recursive evaluation >> class Factorial<1> { >> public: >> enum {value = 1}; >> }; > 0! is 1, so this should be "class Factorial<0>..." Yes. And it gives an incorrect result if the correct result exceeds LONG_MAX. Another specialization could perhaps be used for that case. One rather poor approach is #define ERROR 0 class Factorial<13> { public: enum {value = ERROR}; }; on a system where LONG_MAX==2147483647, since 12! = 479001600. Factorial<1000000L> will still probably give a template stack-depth error on any compiler. I thought it would be interesting to try to improve on that, since I am just starting to study templates. I couldn't see a direct way to specialize on the condition N>12 because the standard seems to require an integral constant, so I tried a few other ideas. None of them is nearly perfect, so I'd like to ask for comments from people with greater knowledge. I tried the following replacements for the enum in template class Factorial { public: enum {value = N * Factorial::value}; }; omitting the specializations for 0 and 13. [snip] enum {value = N * Factorial < N - (N == 0) ? N // N-N is zero :(0::value }; The idea is to attack the recursion depth directly. Instead of always using , I substitute an expression that evaluates to N-1 only for N in [1, 12], otherwise to 0. I really had hopes for this one, but egcs rejects it: `N' was not declared in this scope However, does this attempt not conform to the latest standard? It seems to me that the ?: expression has integral type and is constant because N is constant. */