C ++ статический список с приватным конструктором

Я прошу прощения, если это спросили, я не уверен, как это лучше всего сказать, и не мог найти его.

По сути, у меня есть класс, для которого я хочу сохранить карту, и этот список должен содержать единственные экземпляры объекта.

using std::unordered_map;
class MyClass
{
~MyClass() {};
MyClass() {};   // these actually contain code which operate on the classes data
static unordered_map<Uint32, MyClass> list;
public:
static const MyClass& GetObject(Uint32 key) {return list[key];};

};

Когда я компилирую свой код, он в основном дает мне кучу ошибок из STL о том, что он вызывает удаленные функции и тому подобное, что имеет смысл, потому что unordered_map, вероятно, использует конструктор и деструктор, поэтому я объявил unordered_map другом

friend class unordered_map<Uint32, MyClass>;

Однако, похоже, ошибок не меньше, что я предполагаю из-за классов, используемых unordered_map, таких как pair и hash. Поэтому мой вопрос: есть ли альтернатива этому? Должен ли я просто объявить больше друзей, которые, по-видимому, выдают ошибки из компилятора, или есть другой метод?

0

Решение

ОБНОВЛЕНИЕ: T.C. любезно указал пару вещей, которые я упустил из виду, так что этот ответ сделал полный оборот …

#include <iostream>
#include <unordered_map>
#include <map>
#include <cinttypes>

class MyClass
{
typedef std::unordered_map<uint32_t, MyClass> Instances;
friend Instances;
friend std::pair<uint32_t, MyClass>;
friend std::pair<const uint32_t, MyClass>;
public:
static const MyClass& getObject(uint32_t key) { return instances_[key] = 2 * key; }
~MyClass() {}
int n() const { return n_; }
private:
MyClass() : n_(-1) { }
MyClass& operator=(int n) { n_ = n; return *this; }
int n_;
static Instances instances_;
};

MyClass::Instances MyClass::instances_;

int main() {
const MyClass& m20 = MyClass::getObject(20);
const MyClass& m21 = MyClass::getObject(21);
std::cout << m20.n() << ' ' << m21.n() << '\n';
}

Выше кода на ideone.com.

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

В качестве альтернативы вы можете хранить (умные) указатели в unordered_map,

1

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

Так. Вы в настроении делать что-то раздражающее. Итак, давайте сделаем это. Как говорит AlexD, вам не хватает публичного деструктора. Для unordered_map необходим доступ к нему (возможно, через некоторый внутренний класс, определенный реализацией).

Итак, давайте сделаем это, и давайте сделаем то, что вы должны были сделать в первую очередь, то есть сделать намного меньший и более простой контрольный пример:

#include <unordered_map>

class MyClass {
public:
~MyClass() {}

private:
MyClass() {}
};

int main() {
std::unordered_map<int, MyClass> x;
x.at(3);
//x[3];
}

Теперь это хорошо компилируется.

Теперь обратите внимание, что я закомментировал x[3], Мы не можем использовать это. Это потому, что если 3 не существует на карте, мы бы назвали конструктор по умолчанию MyClass, который является частным. И поскольку компилятор не знает во время компиляции, правда ли это, он должен убедиться, что он может вызвать конструктор.


Из комментариев есть опасение, что вы не можете вставить какие-либо объекты в эту карту. Хорошо, давайте добавим статический метод фабрики и избавимся от этой проблемы:

#include <unordered_map>
using std::unordered_map;

class MyClass {
public:
static MyClass factory() { return MyClass(); }
~MyClass() {}

private:
MyClass() {}
int x;
};

int main() {
std::unordered_map<int, MyClass> x;
x.insert(std::make_pair(3, MyClass::factory()));
x.emplace(4, MyClass::factory());
}
2

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