Как обрабатывать разные типы данных, используя один контейнер? - PullRequest
0 голосов
/ 14 октября 2018

У меня есть сторонний 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 Ответ

0 голосов
/ 14 октября 2018

Вы без необходимости конвертируете информацию времени компиляции в структуры данных времени выполнения.Вам не нужно.Рассмотрим что-то вроде этого:

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

Компилятор будет искать правильный вектор по типу во время компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...