Access and inherited constructor templates
_N4527_.12.9 [class.inhctor]
Daveed Vandevoorde

Created on 2013-07-16.00:00:00 last changed 49 months ago


Date: 2014-06-15.00:00:00

Additional note (June, 2014):

This issue is being returned to "review" status in light of a suggestion for an alternative approach to the problem; see issue 1941.

Date: 2014-02-15.00:00:00

Proposed resolution (February, 2014):

Change _N4527_.12.9 [class.inhctor] paragraph 4 as follows:

A constructor so declared has the same access as the corresponding constructor in X. It is deleted if the corresponding constructor in X is deleted (9.5 [dcl.fct.def] 9.5.3 [dcl.fct.def.delete]). While performing template argument substitution (13.10.3 [temp.deduct]) for constructor templates so declared, name lookup, overload resolution, and access checking are performed in the context of the corresponding constructor template of X. [Example:

   struct B {
     template<class T> B(T, typename T::Q);

   class S {
     using Q = int;
     template<class T>
     friend B::B(T, typename T::Q);

   struct D : B {
     using B::B;

   B b(S(), 1); // OK: B::B is a friend of S
   D d(S(), 2); // OK: access control is in the context of B::B

end example] An inheriting constructor shall not be explicitly instantiated (13.9.3 [temp.explicit]) or explicitly specialized (13.9.4 [temp.expl.spec]).

Date: 2015-10-15.00:00:00

[Adopted at the October, 2015 meeting as P0136R1.]

Consider the following example:

  template<class T> struct S {
    typedef int X;
    friend struct B;

  struct B {
    template<class T> B(T, typename T::X);

  struct D: B {
    using B::B;

  S<int> s;
  B b(s, 2); // Okay, thanks to friendship.
  D d(s, 2); // Error: friendship is not inherited.

My understanding is that the construction of d fails because typename T::X expands to S<int>::X in this case, and that is not accessible from D.

However, I'm not sure that makes sense from a usability perspective. The user of D just wanted to be able to wrap class B, and the fact that friendship was granted to B to enable its constructor parameter seems like just an implementation detail that D shouldn't have to cope with.

Would it perhaps be better to suspend access checking during the instantiation of inheriting member function template declarations (not definitions), since real access problems (e.g., the selection of a private constructor) would presumably be revealed when doing the full instantiation?

Date User Action Args
2017-02-06 00:00:00adminsetstatus: dr -> cd4
2015-11-10 00:00:00adminsetstatus: drafting -> dr
2014-07-07 00:00:00adminsetmessages: + msg5095
2014-07-07 00:00:00adminsetstatus: ready -> drafting
2014-03-03 00:00:00adminsetmessages: + msg4841
2014-03-03 00:00:00adminsetstatus: drafting -> ready
2013-10-14 00:00:00adminsetstatus: open -> drafting
2013-07-16 00:00:00admincreate