------- 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

Reply via email to