According to CWG 727, the following code should be accepted; i.e. full specialization may be declared inside class definition. struct A { template<class T> struct B; template <> struct B<int*> { }; }; And per [temp.expl.spec] paragraph 2, An explicit specialization may be declared in any scope in which the corresponding primary template may be defined ([namespace.memdef], [class.mem], [temp.mem]).
The error message for the code (from gcc8.0.1): error: explicit specialization in non-namespace scope
I ran into the same problem. I confirm this problem still exists in the current HEAD (10.0.0), as well as 9.x and 8.x. clang compiles the snippet fine. See my case here: https://wandbox.org/permlink/l5yYYGqsimSQ6Q6M
https://wg21.link/cwg727 N.B. this is a C++17 feature that does not seem to have been approved as a DR, but Clang supports it in all language modes. Carlo, as an aside, your allocator fails to meet the allocator requirements. Rebinding must be reversible, so A<T>::rebind<U>::other::rebind<T>::other must give you back A<T>.
*** Bug 95160 has been marked as a duplicate of this bug. ***
(In reply to Jonathan Wakely from comment #3) > https://wg21.link/cwg727 > > N.B. this is a C++17 feature that does not seem to have been approved as a > DR, but Clang supports it in all language modes. > CWG 727 says "Adopted at the February/March, 2017 meeting", and [temp.class.spec]/5 in ISO/IEC 14882:2017(E) is reflecting the new wording. So this is in C++17. The defect is on GCC side.
(In reply to Rustam Abdullaev from comment #5) > (In reply to Jonathan Wakely from comment #3) > > https://wg21.link/cwg727 > > > > N.B. this is a C++17 feature that does not seem to have been approved as a > > DR, but Clang supports it in all language modes. > > > CWG 727 says "Adopted at the February/March, 2017 meeting", and > [temp.class.spec]/5 in ISO/IEC 14882:2017(E) is reflecting the new wording. > So this is in C++17. The defect is on GCC side. Yes. That's what I said. But it's not a DR, so it only applies to C++17 and not C++14 or older standards.
Compare to e.g. http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1825 which says "[Moved to DR at the November, 2016 meeting.]" That means it's a retroactive fix for previous standards. That isn't the case for 727.
*** Bug 96219 has been marked as a duplicate of this bug. ***
> But it's not a DR, so it only applies to C++17 and not C++14 or older > standards. Isn't it? Its motion does say "accept as Defect Reports".
(In reply to S. Davis Herring from comment #9) > > But it's not a DR, so it only applies to C++17 and not C++14 or older > > standards. > > Isn't it? Its motion does say "accept as Defect Reports". I'm only going by what the issues list says. If that's wrong we should ask Mike to update it.
(In reply to Jonathan Wakely from comment #10) > I'm only going by what the issues list says. If that's wrong we should ask > Mike to update it. FTAOD, what I meant was that I *was* only going by what the issues list says when I claimed it's not a DR. I didn't mean to imply that I *will* only go by what the issues list says in all cases. So when GCC implements it, it should be for every mode.
see https://bugzilla.mozilla.org/show_bug.cgi?id=1677690 for a real world example
I vaguely remember us supporting this in the distant past, but removing that support to be conforming. Ah, yes, in 1998: r0-18485
*** Bug 101848 has been marked as a duplicate of this bug. ***
*** Bug 93992 has been marked as a duplicate of this bug. ***
*** Bug 103232 has been marked as a duplicate of this bug. ***
This won't be implemented in time for GCC 12, sadly. FWIW a class-scope explicit specialization should in most cases be equivalent to an appropriately constrained partial specialization. So as a workaround, instead of e.g.: struct A { template<class T> struct B; template<> struct B<int> { }; // unsupported class-scope explicit specialization }; in C++20 one can do: struct A { template<class T> struct B; template<std::same_as<int> T> struct B<T> { }; }; or in C++17: struct A { template<class T, class = void> struct B; template<class T> struct B<T, std::enable_if_t<std::is_same_v<int, T>>> { }; };