В моей программе мне нужна фабричная функция, которая предоставляет экземпляры отдельного класса, потому что мне нужно контролировать детали каждого экземпляра и знать, сколько экземпляров существует одновременно. В частности, возвращение std :: shared_ptr является идеальным, но изначально это невозможно из-за известной проблемы с функциями "make" для типов std :: pointer, поскольку они также должны были бы дружить с моим классом Widget, который не является не переносится, так как он полагается на текущую реализацию тех методов, которые могут измениться.
Чтобы обойти это, я хочу использовать идиому Passkey, которая была напрямую рекомендована для этой ситуации, как описано в нижней части этого : https://abseil.io/tips/134. Я также основывал свою реализацию на уроках, извлеченных здесь: https://arne-mertz.de/2016/10/passkey-idiom/
Это пример проекта, в котором используются те же настройки, что и в моем полном проекте:
#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;
}
Однако я получаю
Error C2248 'Widget::Key::Key': cannot access private member declared in class 'Widget::Key' TestProject ...\include\xmemory 204
Это меня полностью потеряло, поскольку ошибка исходит из xmemory. cpp указывает, что std :: make_shared все еще пытается получить доступ к частному конструктору. Насколько мне известно, создание экземпляра Key происходит внутри функции factoryMake (), которая принадлежит Factory, а затем этот экземпляр передается в функцию std :: make_shared; следовательно, std :: make_shared не должен нуждаться в доступе к конструктору Key, поскольку ему передается уже созданный экземпляр, что и составляет весь смысл использования этой идиомы в данном контексте. Сам класс publi c, поэтому у него не должно возникнуть проблем с взаимодействием с типом Key, только конструктор должен быть недоступен.
В конце я могу просто пропустить использование std :: make_shared и вместо этого использовать shared_ptr (* T) конструктор с необработанным указателем, но он немного менее эффективен из-за того, что он требует дополнительного выделения, как отмечалось в моей первой ссылке. Это не имеет большого значения, поскольку я не делаю много виджетов, но в конечном итоге я бы предпочел, чтобы работала более идеальная реализация.
Что мне здесь не хватает?