-1

I have made struct std::is_invocable be a friend of class D, but it is unable to access the private member of D. This happens with gcc, clang, and MS Visual Studio 2017, so it is not one of MSVC's quirks.

#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";  // shouldn't this compile if 
                                                                                     // std::is_invocable is friend?
    cout << std::is_invocable<decltype(&E::sinx), E&, const double>::value << "\n";
    
    cout << "Press ENTER to exit.\n";
    std::getline(cin, s);
}

The error is:

C2248 "'D::sinx': cannot access private member declared in class 'D'"

Why can't std::is_invocable access D::sinx()?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
TRPh
  • 187
  • 1
  • 9

1 Answers1

4

Why can't std::is_invocable access D::sinx() ?

Because it isn't trying to. main is trying to access D::sinx. Which it can't. Remember: accessibility is about who can use the name of the member. You typed the name "D::sinx" in main. Therefore, it is main that is trying to access the name.

So you're giving access to the wrong thing.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982