This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Bug report
- To: egcs <egcs-bugs at cygnus dot com>
- Subject: Bug report
- From: Greg Chicares <chicare at ibm dot net>
- Date: Mon, 14 Sep 1998 23:02:09 -0400
- Reply-To: chicare at ibm dot net
// 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 <iostream>
template <int N> class Factorial {
public:
enum {value = N * Factorial
< N -
(N == 0) ? N
:(0<N && N<=12) ? 1
: N
>::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 <int N> class Factorial {
>> public:
>> enum {value = N * Factorial<N-1>::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 <int N> class Factorial {
public:
enum {value = N * Factorial<N-1>::value};
};
omitting the specializations for 0 and 13.
[snip]
enum {value = N * Factorial
< N -
(N == 0) ? N // N-N is zero
:(0<N && N<=12) ? 1 // N-1 as in original template
: N
>::value
};
The idea is to attack the recursion depth directly. Instead of
always using <N-1>, 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.
*/