Search code examples
c++c++11design-patternsfriend-class

Why won't this code, implementing PassKey pattern, compile?


Here is the code, c++11 :

#include<stdio.h>
#include<iostream>

template<typename T>
class Passkey
{
    friend T;
    Passkey() {}
    Passkey(const Passkey&) {}
    Passkey& operator=(const Passkey&) = delete;
};

class Access;

class MyClass
{
   public:
      MyClass() {}

   private:
      void func(Passkey<Access>) { std::cout<<"here" << std::endl;}
};

class Access
{
    public:
      void tryme(MyClass& c) { c.func(Passkey<Access>());} 
};

int main ()
{
   MyClass c;
   Access a;
   a.tryme(c);
   return 0;
}

Compiler is giving the following errors:

prog.cpp: In member function 'void Access::tryme(MyClass&)':

prog.cpp:21:12: error: 'void MyClass::func(Passkey<Access>)' is private
           void func(Passkey<Access>) { std::cout<<"here" << std::endl;}
                ^

prog.cpp:27:56: error: within this context
     void tryme(MyClass& c) { c.func(Passkey<Access>());} 

Solution

  • As pewt said, MyClass::func() must be public in order for Access::tryme() to be able to access it. In the example you linked in the comments, Citizen::getSocialSecurityNumber() is actually public. And that is fine, because the access is limited in a different way.

    Your MyClass::func() takes a Passkey<Access> parameter – and no one is actually allowed to construct such an object apart from the Access class itself. All of Passkey's functions are private. By construction, Access is the only friend of Passkey<Access>, so only Access can construct the “key” required to call func(). So func() behaves as if it were private, without actually being private itself.