Search code examples
c++language-lawyertemplate-specializationaccess-controltemplate-instantiation

Origin story of [temp.spec]/6?


[temp.spec]/6 reads:

The usual access checking rules do not apply to names in a declaration of an explicit instantiation or explicit specialization, with the exception of names appearing in a function body, default argument, base-clause, member-specification, enumerator-list, or static data member or variable template initializer. [ Note: In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) may be private types or objects that would normally not be accessible. — end note ]

What was the motivation behind this rule? Which proposal introduced it (or is it ancient?), and what for?


Solution

  • This wording was added to address issue 6.40 from N0841 (from 1996):

    6.40 Clarication of access checkin in explicit instantiation directives.

    This issue and its resolution are from Bill Gibbons' reflector posting c++std-ext-3258.
    Status: Open
    Bill Gibbons raised the issue that it is not possible to explicitly instantiate templates where the template arguments or other components of the explicit instantiation directive reference types that are not accessible.

    namespace N {
      template <class T> void f(T);
    }
    namespace M {
      class A {
        class B {};
        void f() {
          B b;
          N::f(b);
        }
      };
    }
    template void N::f(M::A::B); // should be allowed
    

    The issue suggests the wording

    The usual access checking rules do not apply to explicit instantiations. In particular, the template arguments, and names used in the function declarator (e.g., including parameter types, return types, and exception specifications) may be private types or objects which would normally not be accessible and the template may be a member template or member function which would not normally be accessible.

    Which was then adopted as part of N0892, and has been the rule since C++98.