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

前端 未结 4 1868
清歌不尽
清歌不尽 2021-02-13 13:45

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 cre

相关标签:
4条回答
  • 2021-02-13 14:32

    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);
    }
    
    0 讨论(0)
  • 2021-02-13 14:34
    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);
        ...
    }
    
    0 讨论(0)
  • 2021-02-13 14:42

    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));
    
    0 讨论(0)
  • 2021-02-13 14:44

    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));
    }
    
    0 讨论(0)
提交回复
热议问题