Я прошу прощения, если это спросили, я не уверен, как это лучше всего сказать, и не мог найти его.
По сути, у меня есть класс, для которого я хочу сохранить карту, и этот список должен содержать единственные экземпляры объекта.
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. Поэтому мой вопрос: есть ли альтернатива этому? Должен ли я просто объявить больше друзей, которые, по-видимому, выдают ошибки из компилятора, или есть другой метод?
ОБНОВЛЕНИЕ: 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
,
Так. Вы в настроении делать что-то раздражающее. Итак, давайте сделаем это. Как говорит 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());
}