[Bug c++/35394] Agressive template instantiation?
proy at clg dot qc dot ca
gcc-bugzilla@gcc.gnu.org
Tue Mar 4 04:28:00 GMT 2008
------- 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
More information about the Gcc-bugs
mailing list