Почему существует дыра для проверки доступа для явных шаблонных экземпляров?

[temp.explicit] содержит следующую формулировку:

Обычные правила проверки доступа не применяются к именам, используемым для указания явных экземпляров. [Примечание: в в частности, аргументы шаблона и имена, используемые в деклараторе функций (включая типы параметров, возвращаемые типы и спецификации исключений) могут быть частными типами или объектами, которые обычно не были бы доступный, и шаблон может быть шаблоном-членом или функцией-членом, которая обычно не была бы доступны. -end note]

Почему эти правила отключены специально для этого случая? В крайнем случае это позволяет произвольный доступ любого частного члена любого класса определенным образом (demo - нулевые предупреждения):

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;
}

Так что недостаток этого правила. Что наверху? Почему нам нужно это отверстие, чтобы избежать проверки доступа?

Ответ 1

Этот вопрос охватывает Herb Sutter GotW # 76. Ожидается, что функции-члены смогут получить доступ к закрытым членам класса. Когда функция-член является шаблоном, вы ожидаете, что сможете специализироваться на таком шаблоне. Это конфликт между моделью управления доступом С++ и моделью шаблонов, чего можно избежать, усложняя (уже сложный) стандарт С++. Хотя можно обойти контроль доступа С++ и доступ к частным членам таким образом, вам настоятельно рекомендуется не делать этого.

Примечание: @Xeo уже объяснял большинство этих пунктов в своих комментариях выше.