Отображение векторных указателей разных типов

#c #mapping #stdvector

#c #отображение #stdvector

Вопрос:

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

 std::vector<class1> vec1;
std::vector<class2> vec2;
std::vector<class3> vec3;

mapper.addVectorPtr(amp;vec1);
mapper.addVectorPtr(amp;vec2);
mapper.addVectorPtr(amp;vec3);

std::vector<class1> * ptr1 = mapper.getVectorPtr<class1>;
std::vector<class2> * ptr2 = mapper.getVectorPtr<class2>;
std::vector<class3> * ptr3 = mapper.getVectorPtr<class3>;
  

Вероятно, я мог бы использовать пользовательский класс с векторным указателем в качестве члена, который был бы производным от общего базового класса. Затем я мог бы перенести их в нужный класс и получить указатель, но я хотел бы посмотреть, есть ли какие-то лучшие варианты.

Комментарии:

1. Знаете ли вы class1 … class N во время компиляции? Или вы ищете полностью универсальное решение?

2. @quantdev Не могли бы вы немного уточнить? Это должно работать для любого класса, если вы это имеете в виду.

Ответ №1:

Вы должны проверить http://www.cplusplus.com/reference/typeinfo/type_info / . Вы можете получить typeinfo таким образом. Позволяет создавать карту с целым числом (= хэш-кодом) в качестве ключа.

затем вы можете реализовать свой mapclass следующим образом (требуется конструктор без аргументов)

 #include <vector>
#include <typeinfo>
#include <map>
#include <iostream>

class typemap{
    std::map<unsigned long, void*> m_ptrs;
public:
    template<typename A>
    void addVectorPtr(std::vector<A>* b){
        A a;
        m_ptrs[ typeid(a).hash_code() ] = b;
    }

    template<typename A>
    std::vector<A>* getVectorPtr(){
        A a;//this is why you need the default constructor
        return (std::vector<A>*) (m_ptrs[ typeid(a).hash_code() ]);
    }
};


int main(){
    std::vector<int>* t1 = new std::vector<int>(3,3);
    typemap tm;
    tm.addVectorPtr(t1);

    std::vector<int> v=*(tm.getVectorPtr<int>());

    for(auto it = v.begin(); it!= v.end();   it){
        std::cout<<*it<<std::endl;
    }
}
  

Комментарии:

1. Я думаю, это то, что я ищу. Я бы использовал type_index для сопоставления, но по какой-то причине приведение из void * мне вообще не приходило в голову!

2. @Veritas Я на самом деле пытаюсь заставить его работать здесь, но, похоже, у меня это не получается. В этом примере, безусловно, много ошибок

3. Может быть, я не проверял. Это подход, который мне нравится.

4. Мне было интересно, что, если мы заменим addVectorPtr шаблонной функцией addVector, которая создаст вектор и сохранит его внутри в mapper? getVectorPtr будет заменен шаблонной функцией getVector, которая вернет ссылку на требуемый вектор. Должен ли я следовать своему первоначальному решению и создавать пользовательский базовый класс и производный класс с помощью std::vector в качестве его члена, а затем приводить по мере необходимости и впоследствии извлекать вектор, или есть лучшее решение?

5. Если я правильно понимаю, все стало бы намного сложнее. Реализация того, что вы хотите, проста: просто определите addVector() так, чтобы он вызывал «addVectorPtr(new std::vector<type>);» и реализуйте addVector следующим образом: » return getVectorPtr() «. Реальная трудность заключалась бы в написании деструктора, я пока не вижукак бы вы это сделали, не имея базового типа, поскольку вы не можете удалить указатель void.