2015-07-09 3 views
0
template <class T> class Foo {}; 

class Manager { 
    std::unordered_map<size_t, std::unique_ptr<std::vector<void *>>> _mFoos; 

public: 
    template <class T> void addFoo(Foo<T> &foo) { 
     int x = typeid(T).hash_code(); 

     // Safe ? : 
     auto &p = *(reinterpret_cast<std::unique_ptr<std::vector<Foo<T>>> *>(&_mFoos[x])); 

     if (p == nullptr) { 
      p.reset(new std::vector<Foo<T>>); 
     } 

     auto &foos = *p; 
     foos.push_back(foo); 
    }; 

    template <class T> Foo<T> &getFoo(int index) { 
     int x = typeid(T).hash_code(); 
     auto it = _mFoos.find(x); 

     auto &foos = *(reinterpret_cast<std::vector<Foo<T>> *>(it->second.get())); 

     return foos[index]; 
    }; 
}; 

Безопасно ли и доступно для reinterpret_cast уникальное_ptr < T> in unique_ptr < T2> если T и T2 - два разных типа? Имеют ли они одинаковый размер и одну и ту же битовую диаграмму?Можно ли конвертировать тип уникального_ptr?

+0

В качестве побочного примечания, я думаю, что ваши указатели находятся не в нужных местах. У вас есть указатель на «вектор», а затем на «вектор» указателей. –

+0

Пожалуйста, 1 вопрос за раз. – sehe

ответ

2

Номер

Casting между несвязанными типами (и различными экземплярами шаблона не имеет отношения типа) не определенно поведение в соответствии с правилом строгого наложения спектров.

+0

Хорошо, спасибо, поэтому вместо использования unique_ptr я могу использовать void * (и управлять собственностью указателя самостоятельно), это нормально со строгим правилом псевдонимов (std :: vector * -> void * -> std :: vector *)? – Johnmph

+0

'unique_ptr' здесь не проблема :-) Как отмечают другие, это не влияет на поведение каста. Если у вас есть два разных типа, то нет смысла хранить их в одном векторе. Особенно если вы разрешите общий метод get(). –

+0

Метод getFoo также является шаблоном, я знаю все типы, которые мне нужны во время компиляции, поэтому я хочу избежать любого виртуального метода/динамического полиморфизма. Все, что мне нужно - это контейнер (unordered_map), который содержит разные типы но поскольку это невозможно, я создаю новый объект типа, а затем его указатель на общий тип (void *), чтобы сохранить его в контейнере, но каждый раз, когда я использую этот объект, я знаю его истинный тип, потому что я обращаюсь к нему только с помощью шаблона метод, который вызывается с правильным типом. – Johnmph

2

(Sidenote Видимо, я должен констатировать очевидное:. Не reinterpret_cast, пожалуйста, см When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?)

С shared_ptr можно использовать

Для unique_ptr вам придется d o преобразование с перемещением. C++ 17 реализует преобразующий конструктор:

template<class U> explicit unique_ptr(U p); 

См http://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr

2-4) в специализации для массивов ведут себя так же, как конструкторы, которые принимают параметр указателя в основного шаблона, за исключением что они будут участвовать только в разрешении перегрузки, если либо U того же типа, как указатель, или указатель того же типа, как и element_type*U некоторый тип указателя V* таким образом, что V(*)[] является implic itly конвертируется в element_type(*)[].

+0

Это потребует, чтобы базовые типы были действительно связаны. –

+0

С тех пор я добавил соответствующие снимки. Конечно, типы должны быть связаны (но это не имеет ничего общего с unique_ptr) – sehe

+0

Ну, да. Но 'unique_ptr' является лишь частью вопроса. Он также спрашивает, безопасно ли это между «vector » и «vector >». –

0

Применяются обычные правила; вы можете только reinterpret_cast получить результат от .get() до типа, если unique_ptr был построен с указателем этого типа.

Поведение литья на любой другой тип не определено.

Смежные вопросы