Given these definitions
template<class T> class foo {};
template<class T> class foo1 { static int i; };
class bar { class baz {}; };
I'm surprised to see that this compiles
template<>
class foo<bar::baz> {};
but this fails with the error 'class bar::baz' is private
template<>
int foo1<bar::baz>::i = 42;
When does this happen, and is there a workaround other than making the type public?
Member functions can be function templates in several contexts. All functions of class templates are generic but aren't referred to as member templates or member function templates. If these member functions take their own template arguments, they're considered to be member function templates.
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
What are the two specializations of I/O template classes in C++? Explanation: The I/O specialization is made with wide character and 8-bit characters.
Member functions of class templates (C++ only)You may define a template member function outside of its class template definition. The overloaded addition operator has been defined outside of class X . The statement a + 'z' is equivalent to a. operator+('z') .
Consider CWG #182:
Certain access checks are suppressed on explicit instantiations. 14.7.2 [temp.explicit] paragraph 8 says […] I was surprised that similar wording does not exist (that I could find) for explicit specializations. I believe that the two cases should be handled equivalently in the example below (i.e., that the specialization should be permitted).
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
[…]
Rationale (October 2002):
We reconsidered this and decided that the difference between the two cases (explicit specialization and explicit instantiation) is appropriate. The access rules are sometimes bent when necessary to allow naming something, as in an explicit instantiation, but explicit specialization requires not only naming the entity but also providing a definition somewhere.
GCC and Clang do indeed reject the last line of the example shown, which is - apparently - inconsistent behavior, as for a corresponding explicit specialization of a class template, they do not issue 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. So I'll go out on a limb here and call both cases you showed ill-formed by §14.3/3:
The name of a template-argument shall be accessible at the point where it is used as a template-argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With