Ni55aN
@Ni55aN

Список объектов с разными template?

Нужно в vector(или списке) хранить экземпляры моего класса, которые могут иметь разные типы в template
template<typename T>
class A{
    T val;
    typedef T type;
    public: A(T v){
        val = v;
    }
    
    T get(){
        return val;
    }
};


Если попробовать хранить только указатель на void, то при получении элементов из списка неизвестен их тип
int main()
{
    std::vector<void*> v;
    A<int>* a = new A<int>(8);
    v.push_back(a);
    auto first = v.at(0);
    printf("%d",((A<int>*)first)->get());
}


Основная задача заключается в том, чтобы сформировать список из разнотипных данных, которые будут обработаны в другом месте, а значит, необходимо знать их типы. Вроде бы для этой задачи подходят кортежи, но пока не опробовал их
  • Вопрос задан
  • 303 просмотра
Решения вопроса 2
devalone
@devalone
̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻
А как вы себе это представляете? Вектор - шаблонный класс и параметр шаблона задаёт тип. Поэтому вам нужно искать что-то готовое для этой цели или мудрить своё. Информацию о типе в любом случае где-то хранить придётся(ну или помнить что куда складывали, но это неудобно и не всегда получится), т.к. элемент контейнера - это просто набор байтов. Я вижу 2 варианта:
1 выделять память большим куском и где-то сохранять информацию о типе, скажем так:
до 4 байта - int, до 12 байта - double, до 50 байта - SomeType. Можно хранить в том же блоке данных перед каждым элементом. Для хранения информации о типе в C++ есть RTTI, там не так много возможностей, но всё же.
2 хранить указатель на void и опять же тип, но на этот раз для каждого элемента.
Если планируется хранить данные примерно так: [int, int , int, int, double, Color, Color, Color, Color, Color, Color], то можно сэкономить, сохраняя диапазоны.
Первый вариант лучше тем, что данных не разбросаны по памяти.
Погуглите, я думаю оба варианта уже кто-то реализовал.

UPD: набросал на коленке первый вариант https://github.com/DevAlone/c-universal-container/...
Ответ написан
Ni55aN
@Ni55aN Автор вопроса
Получилось реализовать следующим образом, расширив под это smart pointer
1. запись значения
а) значение передается по указателю и записывается как void*
б) записывается тип (typename) в type_info, таким образом
2. чтение
а) по typename проверяют нужный тип
б) получаю значение с указанием того же typename (именно это неудобно, так как приходится явно указывать тип, зато его можно узнать из type_info)
class IOData : public std::shared_ptr<void> {
  const std::type_info *ti;

public:
  template <typename T> void reset(T *ptr) {
    std::shared_ptr<void>::reset(ptr);
    ti = &typeid(T);
  }
  template <typename T> bool isType() { return typeid(T) == *ti; }
  template <typename T> T get() { return *(T *)std::shared_ptr<void>::get(); }
};
typedef std::vector<IOData> OutputData;
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
dio4
@dio4
team leader, system engineer, master of sports
разве вектор не предназначен для хранения однотипных данных?
Я тут подумал - может ассоциативный массив? "объект - его тип"...
Ответ написан
vt4a2h
@vt4a2h Куратор тега C++
Senior software engineer (C++/Qt/boost)
Кортежи или вектор объектов типа вариант.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы