When can you specialize a template for a private member type?

Given these definitions

template<class T> class foo {}; template<class T> class foo1 { static int i; }; class bar { class baz {}; }; 

I am surprised to see that this compiles

 template<> class foo<bar::baz> {}; 

but this is not with the error 'class bar::baz' is private

 template<> int foo1<bar::baz>::i = 42; 

When does this happen, and is there a workaround different from making a type publication?

+7
c ++ templates
source share
1 answer

Consider CWG # 182 :

Some access checks are suppressed by explicit instantiations. 14.7.2 [temp.explicit] in clause 8 says [...] I was surprised that such a formulation does not exist (what I can find) for explicit specializations. I believe that these two cases should be handled equivalently in the example below (i.e. that specialization should be allowed).

 template <class T> struct C { void f(); void g(); }; template <class T> void C<T>::f(){} template <class T> void C<T>::g(){} class A { class B {}; void f(); }; template void C<A::B>::f(); // okay template <> void C<A::B>::g(); // error - A::B inaccessible 

[...]

Justification (October 2002) :

We reviewed this and decided that the difference between the two cases (explicit specialization and explicit implementation) is appropriate. Access rules are sometimes bent when necessary to allow you to name something, as in an explicit instantiation, but obviously specialization requires not only the name of the object, but also the provision of a definition somewhere.

GCC and Clang really reject the last line of the example, that apparently inconsistent behavior, as well as for the corresponding explicit specialization of the class template, they do not give an error message:

 template <class> struct T { void g(); }; class A { class B; class C; }; template <> struct T<A::B>; // Ok template <> void T<A::C>::g(); // Error 

Demo Therefore, I will go out on a limb and name both cases that you showed poorly formed in Β§14.3 / 3:

The name of the template argument must be available at the point where it is used as the template argument.

+5
source share

All Articles