This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Bug report


// 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.
*/




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]