------- Comment #1 from proy at clg dot qc dot ca 2008-03-04 04:28 ------- For those interested: it might help to know that, on all g++ compilers that I know of and that have this bug (at least from my understanding of the situation), one could replace
template <class Reason> class not_compilable { enum { dummy_value = sizeof (static_assert<false>) }; }; with template <class Reason> class not_compilable { static static_assert<false> dummy_fct (); enum { dummy_value = sizeof (dummy_fct ()) }; }; and it would compile, which (somehow) makes the situation even more suspicious... (In reply to comment #0) > 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 > } > -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35394