[Bug c++/35394] New: Agressive template instantiation?

proy at clg dot qc dot ca gcc-bugzilla@gcc.gnu.org
Wed Feb 27 17:36:00 GMT 2008


I think recent versions of g++ (4.*, for example, but not 3.4.4) go too far
performing C++ template instantiation. Mind you, this is only a guess, and you
guys will know better.

Here's the problem case. The code shown below should (in my opinion) compile
properly as is but should not compile when the 2nd line of main() is not
commented out.

This «non-compilability» of the 2nd line is made on purpose, to simplify static
error checking, and relies on a technique similar to the one made by boost's
static assert on most platforms. The intent is to cause meaningful error
messages in cases where we can "see them coming", without preventing correct
programs to compile. In main(), the 1st line is expected to be legal and the
2nd (when it's not commented out) is illegal. What I see as a bug here is that
the code for generic class not_compilable seems to be considered even when the
code does not use it.

In more detail: the goal of the test cas below is to provoke a compile-time
failure that describes the error using the template parameter Reason in generic
class not_compilable, but only when the static int value used for factorial is
negative. This test code compiles (or does not compile, depending on the case)
fine using most compilers at my disposal (g++ 3.3* and 3.4* included) but most
of my students using g++ 4.* report that this code fails to compile even when
only the 1st line of main() is there. I would like to give you guys more info
but all g++ compilers around me seem to handle this correctly; only "recent
versions" (at least from 4.1* on) seem to mishandle it (at least if one
considers, as I do, the following technique to be valid C++).

The code follows...

// -------------------

//
// static_assert is provided here for clarity; remove it or
// rename it if it is provided by your compiler
//
template <bool>
   struct static_assert;
template <>
   struct static_assert<true> {};

//
// A class made not to compile, on purpose. Since it is generic, my
// expectation is that it should not be considered if it is not being
// used. It is syntactically correct and compiles fine (when not used)
// on older g++ (3.3* to 3.4* at least) and on all compilers at my
// disposal, as mentioned above
//
template <class Reason>
   class not_compilable
   {
      enum { dummy_value = sizeof (static_assert<false>) };
   };

//
// A class that does compile :)
//
struct compilable
{
};

//
// A static type selector
//
template <bool, class, class>
   struct static_if_else;
template <class IfTrue, class IfFalse>
   struct static_if_else<true, IfTrue, IfFalse>
   {
      typedef IfTrue type;
   };
template <class IfTrue, class IfFalse>
   struct static_if_else<false, IfTrue, IfFalse>
   {
      typedef IfFalse type;
   };

//
// An empty class to add meaning when factorial<N> does
// not compile using a negative value for N
//
class negative_value_not_accepted {};

//
// A class that should only compile when N>=0 and that
// should fail otherwise
//
template <int N>
   struct factorial
      : private static_if_else<
           (N<0), not_compilable<negative_value_not_accepted>, compilable
        >::type
   {
      enum { value = N * factorial<N-1>::value };
   };
template <>
   struct factorial<0>
   {
      enum { value = 1 };
   };

//
// The test program. My understanding is that it should compile
// when only the 1st line is included and that it should not
// compile when the 2nd line is included. What I see as a bug is
// that g++ 4.1*+ seems not to accept even the 1st line, considering
// not_compilable even though it is not being used by the program...
//
#include <iostream>
using std::cout;
int main ()
{
   cout << factorial<5>::value; // Cool; should compile
   //cout << factorial<-3>::value; // should not compile
}


-- 
           Summary: Agressive template instantiation?
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: proy at clg dot qc dot ca


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35394



More information about the Gcc-bugs mailing list