Почему существует дыра для проверки доступа для явных шаблонных экземпляров?
[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 уже объяснял большинство этих пунктов в своих комментариях выше.