声明为友元的std::is_invocable无法访问类私有成员原因
为什么声明为友元的
std::is_invocable无法访问类的私有成员 问题现象
- 已将
struct std::is_invocable声明为class D的友元,但它无法访问D的私有成员,该问题在gcc、clang、MS Visual Studio 2017下均会复现,并非MSVC独有兼容问题。
复现代码
#include <iostream> #include <string> #include <type_traits> #include <iomanip> #include <cmath> using std::cin; using std::cout; const double PI = 3.1415926535898; class A { public: A(double xx) : x(xx) { s = sin(x); } double sinx() { return s; } private: double x; double s; }; class B { public: double sinx(double x) { return sin(x); } }; class C { public: static double sinx(double x) { return sin(x); } }; class D { private: double sinx(double x) { return sin(x); } public: template<class T, class... Args> friend struct std::is_invocable; }; class E { public: double sinx; }; int main() { std::string s; A a0(PI/2.); cout << std::boolalpha; cout << std::is_invocable<decltype(&A::sinx), A&>::value << "\n"; cout << std::is_invocable<decltype(&B::sinx), B&, const double>::value << "\n"; cout << std::is_invocable<decltype(&B::sinx), const double>::value << "\n"; cout << std::is_invocable<decltype(&C::sinx), const double>::value << "\n"; cout << std::is_invocable<decltype(&D::sinx), D&, const double>::value << "\n"; cout << std::is_invocable<decltype(&E::sinx), E&, const double>::value << "\n"; cout << "Press ENTER to exit.\n"; std::getline(cin, s); }
编译报错
C2248 "'D::sinx': cannot access private member declared in class 'D'"
原因说明
核心问题是访问权限检查的触发时机和位置完全不在std::is_invocable内部:
- C++的访问控制检查是按代码的词法上下文执行的,你在
main函数(D类的外部、既不是D的成员也不是D的友元的上下文)里写&D::sinx时,编译器首先就会检查当前上下文有没有权限访问D的私有成员sinx,这一步检查在你把结果作为模板参数传给std::is_invocable之前就已经执行,直接触发访问报错。 - 你给
std::is_invocable声明的友元权限,仅允许std::is_invocable自己的实现代码内部访问D的私有成员,不会给外层写&D::sinx的main函数上下文开放访问权限。 - 简单说:你自己在无权限的上下文里先碰了私有成员,这步就已经违规了,和后面接收这个值的
std::is_invocable是不是友元没有任何关系。
内容的提问来源于stack exchange,提问作者TRPh
相关产品推荐
相关产品推荐

