make_unique не компилируется для создания экземпляра синглтона

Все,

Я использую C ++ 14 и делаю более или менее стандартный синглтон. Я использую последнюю версию Visual Studio 2017. Этот код работает:

#include <memory>
class A
{
public:
static A& getInstance()
{
if (instance == nullptr)
instance = std::unique_ptr<A>(new A());
return *instance;
}

private:
A() {}
static std::unique_ptr<A> instance;
};
std::unique_ptr<A> A::instance = nullptr;

Однако, когда я изменяю создание экземпляра синглтона на это:

instance = std::make_unique<A>();

Я получаю ошибку компиляции, когда пытаюсь получить доступ к приватному члену:

Error   C2248   'A::A': cannot access private member declared in class 'A'
c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.14.26428\include\memory   2510

Это похоже на ошибку для меня, так как две формы должны быть идентичны по функции? Мысли?

1

Решение

Цель std::unique_ptr<> это контролировать время жизни объекта, на который указывает. Вы можете передать std::unique_ptr<> вокруг, но это также передаст право собственности на указанный объект. Эта концепция не очень хорошо соответствует концепции синглтона. Существует только одно место, где разрешено создавать (или удалять) синглтон. Вам не нужно std::unique_ptr<>для этого. Как уже говорилось в комментариях, для этого есть более простые способы. Я бы предпочел предложение @ Преториана:

static A& getInstance()
{
static A instance;
return instance;
}

Причина, по которой вы не можете использовать std::make_unique<>() чтобы создать экземпляр вашего класса, конструктор является закрытым. Чтобы получить к нему доступ, вам нужна функция доступа, чтобы быть friend, Посмотри на Как сделать std :: make_unique другом моего класса для этого. Другое решение состоит в том, чтобы предоставить открытый конструктор, требующий частного типа в качестве аргумента, как описано в int это решение.

3

Другие решения

instance = std::make_unique<A>();

это создает A в функции make_unique, Но тот номер, который вы хотите вызвать, является частным.

private:
struct ctor_permission_t{
explicit ctor_permission_t(int){};
};
public:
explicit A(ctor_permission_t):A(){}
};

затем

instance = std::make_unique<A>(ctor_permission_t{0});

ctor_permission_t действует как знак, дающий своему владельцу право создавать A, Мы передаем это make_unique,

explicit int ктор в ctor_permission_t делает невозможным его создание без указания типа и только в пределах экземпляров и друзей A могу назвать это, потому что это личное. Это затрудняет обход этого токена разрешения.

3

По вопросам рекламы [email protected]