Passkey idiom with std::make_shared. xmemory cannot access private Key constructor Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Passkey idiom with std::make_shared. xmemory cannot access private Key constructor without wasting too much if your time.

The question is published on by Tutorial Guruji team.

In my program I need a factory function that provides instances of separate class because I need control over the details of each instance and to be aware of how many instances are in existence at a time. In particular returning a std::shared_ptr is ideal, but this is initially impossible due to a known issue with the “make” fucntions of the std::pointer types as they would need to be friends with my Widget class as well, which isn’t portable since it relies on the current implementation of those methods that may change.

To get around this, I want to employ the Passkey idiom, which was directly recommend for this situation as described at the bottom of this: https://abseil.io/tips/134. I also based my implementation off the lessons learned here: https://arne-mertz.de/2016/10/passkey-idiom/

This is a sample project that uses my same setup as my full project:

#include <iostream>

class Widget
{
public:
    class Key
    {
        friend class Factory;
    private:
        Key() {};
        Key(const Key&) = default;
    };

    int mTest;

    explicit Widget(Key, int test) { mTest = test; }

    int getTestVar() { return mTest; }
};

class Factory
{
public:

    int mTestPass;

    Factory(int input) { mTestPass = input; }

    std::shared_ptr<Widget> factoryMake() { return std::make_shared<Widget>(Widget::Key{}, mTestPass); }
};

int main()
{
    Factory testFactory(10);
    std::shared_ptr<Widget> testWidget = testFactory.factoryMake();

    std::cout << testWidget->getTestVar();

    return 0;
}

However, I get

Error   C2248   'Widget::Key::Key': cannot access private member declared in class 'Widget::Key'    TestProject ...includexmemory 204 

This has me completely lost, since the error coming from xmemory.cpp indicates that std::make_shared is sill trying to access a private constructor. As far as I’m aware, the construction of the Key instance occurs within the factoryMake() function, which belongs to Factory, and then that instance is passed into the std::make_shared function; therefore, std::make_shared should not need access to the Key constructor since an already constructed instance is being passed to it, which is the entire point of using this idiom in this context. The class itself is public so it should have no issues interacting with the type Key, only the constructor should be inaccessible.

In the end I can just skip using std::make_shared and instead use the shared_ptr(*T) constructor with a raw pointer, but this is slightly less efficient due to the extra allocation it requires, as noted in my first link. It isn’t a big deal as I’m not making many widgets but I’d ultimately prefer to get the more ideal implementation working.

What am I missing here?

Answer

The problem is that the compiler needs to copy your Widget::Key when you call std::make_shared, and you have declared the copy constructor private. You can solve this in one of two ways:

  1. Make the copy constructor of Widget::Key public.

  2. Change the Widget constructor to take the Widget::Key by const reference:

    explicit Widget(const Key&, ...

We are here to answer your question about Passkey idiom with std::make_shared. xmemory cannot access private Key constructor - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji