Compiled with gcc 3.3.1 (cygwin), 3.2.3 (gentoo-linux), mingw32 3.2 the test code included in this report generates an endless recursion. It compiles without errors or warnings so the underlying problem can be quite hard to track for the user. $ cat <<EOF >test.cpp #include <iostream> template <bool compare> struct outer { template <bool compare_with,bool second> struct inner // unspecialized compare != compare_with { static inline void test() { std::cout << "invert" << std::endl; // call version with inverted template value inner<! compare_with, ! second>::test(); } }; template <bool second> // specialization compare == compare_with struct inner<compare,second> { static inline void test() { std::cout << "second: " << second << std::endl; } }; }; int main(int argc,char* argv[],char** envp) { // expected output: // invert // second: true outer<false>::inner<true,false>::test(); // expected output: // second: false outer<true>::inner<true,false>::test(); return 0; } EOF $ make test && ./test
Confirmed. Reduced, this looks so: --------------------------- template <bool B1> struct outer { template <bool B2, bool B3> struct inner { static int f() { return inner<!B2,!B3>::N; }; }; template <bool B3> struct inner<B1,B3> { static const int N = 1; }; }; int i = outer<false>::inner<true,false>::f(); --------------------------- This should compile, since in f() we should look into the specialization, but we don't. And never did. W.
And just as a sidenote: this bug may be related to the fact that we reject this explicit (full) specialization in this code: ------------------------- template <bool B1> struct outer { template <bool B2> struct inner { static int f() { return inner<!B2>::N; }; }; template <> struct inner<B1> { static const int N = 1; }; }; int i = outer<false>::inner<true>::f(); ---------------------------- g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ x.cc -c x.cc:7: error: invalid explicit specialization before '>' token x.cc:7: error: explicit specialization in non-namespace scope `struct outer<B1>' x.cc:7: error: enclosing class templates are not explicitly specialized g/x> g/x> icc -c x.cc g/x>
Testcase in comment #2 by Wolfgang is ill-formed because of [temp.expl.spec]/2: explicit specializations must always be defined at namespace scope. Instead, partial specialization can be defined at class scope.
I was basically looking at the first line of errors only, so totally missed the rest. Sorry. The example in #1 should be valid, though. W.
Related to PR4882, PR13088.
Work postponed to GCC 4.1. This bug is tricky to fix.
Won't work on it for a long while.
*** Bug 29767 has been marked as a duplicate of this bug. ***
PR29767 made me try whether we can achieve the same wrong effect for template type parameters, and indeed we can: -------------------- template <typename T> struct outer { template <typename T2, typename U> struct inner { static int f() { return inner<T,int>::N; }; }; template <typename U> struct inner<T,U> { static const int N = 1; }; }; int i = outer<int>::inner<double,int>::f(); ------------------ This compiles with icc, but doesn't with gcc: g/x> /home/bangerth/bin/gcc-4.2-pre/bin/c++ -c x.cc x.cc: In static member function ‘static int outer<T>::inner<T2, U>::f() [with T2 = double, U = int, T = int]’: x.cc:13: instantiated from here x.cc:4: error: ‘N’ is not a member of ‘outer<int>::inner<int, int>’ As PR29767 shows, this can actually lead to wrong code. W.
*** Bug 29830 has been marked as a duplicate of this bug. ***
(In reply to comment #6) > Work postponed to GCC 4.1. This bug is tricky to fix. What is the status of this bug? Will be resolved in the next release? For us is critical because a whole framework is built up on this.:,,,( Unfortunately we don't have any workaround! /jz
Raising severity, some more people in CC. This at least seems to be an often reported problem.
(In reply to comment #12) > Raising severity, some more people in CC. This at least seems to be an often > reported problem. It is not a regression as far as I can tell.
Subject: Re: Specialization of inner template using outer template argument doesn't work > It is not a regression as far as I can tell. True. However it does produce wrong code. W.
This is a duplicate of 4882, however, I don't have the power to mark it as that (not that that would necessarily be a good thing as this contains more recent begging and is flagged with a higher priority).
*** Bug 4882 has been marked as a duplicate of this bug. ***
If anyone ever fixes this, the various duplicates of this bug have a number of interesting variants that may be worth adding to the testsuite as well. W.
Subject: Bug 14032 Author: jason Date: Tue Sep 4 12:27:21 2007 New Revision: 128076 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=128076 Log: PR c++/14032 * pt.c (most_specialized_class): Substitute outer template arguments into the arguments of a member template partial specialization. (strip_innermost_template_args): New fn. Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/pt.c
Subject: Bug 14032 Author: jason Date: Tue Sep 4 12:27:38 2007 New Revision: 128077 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=128077 Log: PR c++/14032 * pt.c (most_specialized_class): Substitute outer template arguments into the arguments of a member template partial specialization. (strip_innermost_template_args): New fn. Added: trunk/gcc/testsuite/g++.dg/template/mem-partial1.C trunk/gcc/testsuite/g++.dg/template/mem-partial2.C
Subject: Bug 14032 Author: jason Date: Tue Sep 4 15:43:00 2007 New Revision: 128090 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=128090 Log: PR c++/14032 * pt.c (most_specialized_class): Substitute outer template arguments into the arguments of a member template partial specialization. (strip_innermost_template_args): New fn. Added: branches/gcc-4_2-branch/gcc/testsuite/g++.dg/template/mem-partial1.C - copied unchanged from r128077, trunk/gcc/testsuite/g++.dg/template/mem-partial1.C branches/gcc-4_2-branch/gcc/testsuite/g++.dg/template/mem-partial2.C - copied unchanged from r128077, trunk/gcc/testsuite/g++.dg/template/mem-partial2.C Modified: branches/gcc-4_2-branch/gcc/cp/ChangeLog branches/gcc-4_2-branch/gcc/cp/pt.c
Fixed for 4.2.2 and 4.3.0.
*** Bug 10574 has been marked as a duplicate of this bug. ***