У меня есть сторонний API, где определено более сотни различных типов структур наряду с некоторыми данными базового класса. Количество структур и их типы могут меняться между выпусками.
Мне нужно динамически создавать и заполнять по крайней мере несколько десятков векторов этих структур (каждый вектор содержит один тип структуры). Наиболее разумным способом доступа (идентификации) этих векторов является их тип данных.
Ниже мой нынешний подход. У меня нет доступа к C ++ 17.
Мой вопрос: я могу покрыть все управление памятью здесь? Создать какие-либо ненужные копии, которых можно избежать?
#include "stdafx.h"
#include <iostream>
#include <memory>
#include <vector>
#include <unordered_map>
#include <typeinfo>
// from a third party API
struct A {
int a;
};
struct B {
int a;
};
// ----
#define mapHash map[typeid(T).hash_code()]
typedef std::unordered_map<size_t, std::shared_ptr<void>> omniMap;
template <class T>
void addVect(omniMap &map) {
if(mapHash == nullptr) {
mapHash = std::make_shared<std::vector<T>>();
}
T s{};
(*std::static_pointer_cast<std::vector<T>>(mapHash)).push_back(std::move(s));
}
template <class T>
std::shared_ptr<std::vector<T>> getVect(omniMap &map) {
return std::static_pointer_cast<std::vector<T>>(mapHash);
}
template <class T>
void addElem(omniMap &map, const T &var) {
mapHash = std::make_shared<T>(var);
}
template <class T>
std::shared_ptr<T> getElem(omniMap &map) {
return std::static_pointer_cast<T>(mapHash);
}
int main()
{
omniMap om;
addVect<A>(om);
addVect<A>(om);
addVect<B>(om);
addElem(om, 5);
addElem(om, 2.5);
addElem<std::string>(om, "hello");
*getElem<int>(om) = 3;
*getElem<double>(om) = 3.7;
(*getVect<A>(om))[1].a = 15;
std::cout <<
(*getVect<A>(om))[1].a << " " <<
*getElem<int>(om) << " " <<
*getElem<double>(om) << " " <<
(*getElem<std::string>(om)).c_str() << std::endl;
return 0;
}
output
15 3 3.7 hello
Всего 1 ответ
Вы не обязательно конвертируете информацию времени компиляции в структуры данных времени выполнения. Вам не нужно. Рассмотрим что-то вроде этого:
namespace internal {
template <typename T>
struct VectorHolder {
static std::vector<T> vect;
};
template <typename T> std::vector<T> VectorHolder<T>::vect;
}
template <typename T>
std::vector<T>& getVect() { return internal::VectorHolder<T>::vect; }
template <class T>
void addVect() {
getVect<T>().emplace_back();
}
// Other functions left as an exercise for the reader
Компилятор будет искать правильный вектор по типу во время компиляции.