Friend function is unable to construct a unique pointer of the class

梦想的初衷 提交于 2019-12-21 03:39:28

问题


I have a certain design strategy where the constructor of my class is private and can only be constructed by friends of the class. Inside the friend function, I am trying to create a unique_pointer of my class using std::make_uniquebut it doesn't compile. My VC12 compiler complains

c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1639): error C2248: 'Spam::Spam' : cannot access private member declared in class 'Spam'

The relevant code which fails during compilation is as follows

#include <memory>
class Spam {
public:
    friend void Foo();

private:
    Spam(int mem) :mem(mem) {}
    int mem;
};
void Foo() {
    std::unique_ptr<Spam> spam = std::make_unique<Spam>(10);
}

Why am I not able to compile?


回答1:


In your case the function make_unique is trying to create an instance of Spam and that function is not a friend. Calling a non-friend function from inside a friend function does not imbue the non-friend function with friend status.

To solve this you can write in Foo:

std::unique_ptr<Spam> spam(new Spam(10));



回答2:


Here is another approach I've seen used, apparently known as the passkey idiom : have the public constructor require a private access token.

class Spam {
    struct Token {};
    friend void Foo();
public:
    Spam(Token, int mem) : mem(mem) {}

private:
    int mem;
};

void Foo() {
    std::unique_ptr<Spam> spam = std::make_unique<Spam>(Spam::Token{}, 10);
}

void Bar() {
    // error: 'Spam::Token Spam::token' is private
    // std::unique_ptr<Spam> spam = std::make_unique<Spam>(Spam::Token{}, 10);
}



回答3:


Why am I not able to compile?

You are unable to compile because make_unique is not a friend of Spam.

An alternative solution to making make_unique a friend is to move the creation of the unique_ptr into Spam.

class Spam {
   ...
private:
   Spam(int) {}

   static unique_ptr<Spam> create( int i ) 
   { return std::unique_ptr<Spam>( new Spam(i) ); }
};

and then have Foo call that instead.

void Foo() {
    std::unique_ptr<Spam> spam = Spam::create(10);
    ...
}



回答4:


In your example, Foo() is a friend, but it isn't the function that's creating the Spam - make_unique is internally calling new Spam itself. The simple fix is to just have Foo() actually construct the Spam directly:

void Foo() {
    std::unique_ptr<Spam> spam(new Spam(10));
}


来源:https://stackoverflow.com/questions/29896268/friend-function-is-unable-to-construct-a-unique-pointer-of-the-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!