2

I'm attempting my first bigger C++ object and I'm running into a bit of a problem when it comes to implementing a singleton using a shared pointer.

When I try to compile the following, I Visual Studio gives me this error:

"Error C2248 'PaletteManager::PaletteManager': cannot access private member declared in class 'PaletteManager' {omitted}\xmemory line 228"

I'm guessing the issue is because I have a private constructor/destructor and make_shared is trying to call the constructor. This access problem makes sense to me, but if I want to use a shared pointer as the way to access my singleton object, what am I supposed to do? The code works just fine with a raw pointer, but I wanted to try and do things the clean way with a smart pointer.

Here is the header file for the code in question:

class PaletteManager
{
private:

    // array representing palette colors
    uint* paletteColors;

    // private constructor/destructor because singleton
    PaletteManager();
    ~PaletteManager();

    // load palette from file TODO: not implemented
    void loadPallette();

    static std::shared_ptr<PaletteManager> instance;

public:

    const uint PALETTE_MAX_COLORS = 4;

    uint getPaletteColor(uint idx);

    // singleton accessor
    static std::shared_ptr<PaletteManager> getInstance();
};

And here is the function at issue in the cpp file:

std::shared_ptr<PaletteManager> PaletteManager::instance = nullptr;

std::shared_ptr<PaletteManager> PaletteManager::getInstance()
{
    if (!PaletteManager::instance) 
    {
        PaletteManager::instance = std::make_shared<PaletteManager>();
    }

    return PaletteManager::instance;
}
RGrun
  • 350
  • 3
  • 16
  • Possible duplicate https://stackoverflow.com/questions/1008019/c-singleton-design-pattern/40337728#40337728 – Galik Feb 15 '21 at 02:17

2 Answers2

3
PaletteManager::instance = std::make_shared<PaletteManager>();

This results in std::make_shared attempting to new a PalletteManager object, and then construct a std::shared_ptr from it. This is what std::make_shared does, that's how it works.

This is not going to work here: that's because PalletteManager has a private constructor, and std::make_shared, the template in the C++ library, is not it's friend.

You will have to explicitly new the object in getInstance, a member of this class, which can use the private constructor, and then manually construct the std::shared_ptr from the pointer to this new object.

TLDR: you cannot use std::make_shared for an object with a private constructor. C++'s rules do not allow you to do that.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
0

You can make std::make_unique<>() a friend function of your class with the private constructor. Presumably this would work with std::make_shared<>() too? (But I haven't tested it.)

For example, see: How to make std::make_unique a friend of my class

NKatUT
  • 429
  • 3
  • 10