You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

声明为友元的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 11:06:29