[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; }
Так что недостаток этого правила. Что наверху? Почему нам нужно это отверстие, чтобы избежать проверки доступа?