12

[temp.explicit] contains this wording:

The usual access checking rules do not apply to names used to specify explicit instantiations. [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 which would normally not be accessible and the template may be a member template or member function which would not normally be accessible. —end note ]

Why are those rules disabled specifically for this case? In the extreme, this allows for arbitrary access of any private member of any class in a well-defined way (demo - zero warnings):

struct A {
private:
  int member;
};

template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};

// tag used to access A::member
struct A_member { 
  typedef int A::*type;
  friend type get(A_member);
};

template struct Rob<A_member, &A::member>;

int main() {
  A a;
  a.*get(A_member()) = 42; // write 42 to it
  std::cout << "proof: " << a.*get(A_member()) << std::endl;
}

So that's the downside of this rule. What's the upside? Why do we need this hole to avoid access checking?

Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    Re: "arbitrary access" -- so what? The type system protects against mistake, not fraud. – Pete Becker Oct 01 '16 at 14:38
  • 2
    C++' s access checking protects against Murphy, not Machiavelli. You can access a protected or private member in other ways (pointer shenanigans, mostly). So yeah. – Xeo Oct 01 '16 at 14:38
  • It is an old and boring topic! – Nawaz Oct 01 '16 at 14:52
  • @Xeo Sure, but presumably if we're giving Machiavelli all this power, we're doing it because it offers some other benefits. I'd like to know what those benefits are. – Barry Oct 01 '16 at 14:52
  • 5
    There might be legitimate reasons for you, as the author of the class, to specialise something. And as specialisations can only happen at namespace scope... – Xeo Oct 01 '16 at 14:54
  • 1
    @xeo add an example and that is an answer! – Yakk - Adam Nevraumont Oct 01 '16 at 15:52
  • @Yakk: Feel free to do so. I don't have a proper example at hand and am otherwise preoccupied right now. :) – Xeo Oct 01 '16 at 16:40

1 Answers1

4

This question is covered by Herb Sutter's GotW #76. Member functions are expected to be able to access private members of a class. When member function is a template, you would expect to be able to specialize such template. This is a conflict between the C++ access control model and the template model, which could be avoided by complicating (already complex) C++ standard. While it is possible to bypass C++ access controls and access private members in this way, you are strongly advised against doing that.

Note: @Xeo already explained most of these points in his comments above.

fiktor
  • 1,303
  • 2
  • 11
  • 22