2014-11-10 2 views
4

У меня все время возникает ошибка, которая имеет смысл, но я не знаю с чего начать.initialize struct with shared_ptr <void>

Вот что я работаю.

#include <memory>                                        

struct Container {                
    int type;                  
    std::shared_ptr<void> payload;            

    Container(int t, const void *p) : type(t), payload(p) { }      
};                    

int main() {                 
    return 0;                  
} 

Я пытаюсь сделать общий контейнер, используя shared_ptr с типом void. Я собирался сделать переключатель типа, а затем просто перевести полезную нагрузку в соответствующий тип.

Я понял, что могу просто сделать что-то вроде Container ctn(1, new Data());, но я думаю, что у меня может быть и это неправильно.

Спасибо.

+4

Просто будьте счастливы, что эта проблема мешает вам идти вперед с этим дизайном. В качестве примера Бертран Мейер решил не поддерживать типы перечислений в Эйфеле, просто чтобы предотвратить ваш дизайн. Это так плохо, экстремальный анти-шаблон, совершенно противоположный объектно-ориентированным. Теперь забудьте о указателях 'void *'. Используйте стандартный контейнер библиотеки. –

+0

'Я пытаюсь создать общий контейнер с помощью shared_ptr' Ok. 'с типом void', который был решен с помощью шаблонов - отбросьте' void * '. C++ не 'C'. – PaulMcKenzie

ответ

2

Вы пытаетесь инициализировать указатель на void с указателем на const void, что действительно является незаконным. «Умность» указателя не имеет значения, это также не подходит для обычных указателей.

Вам необходимо либо изменить тип payload к std::shared_ptr<const void>, или (вероятно, больше, чем вы на самом деле хотите) изменить тип p к void*.

Обратите внимание, однако, что, хотя это будет технически решать непосредственную проблему, оно может ввести более фундаментальное. В соответствии с этим дизайном payload ничего не узнает о фактическом типе, на который он указывает, поэтому он будет не назвать деструктор Data, когда последняя ссылка исчезнет. Вероятно, вы должны переосмыслить весь дизайн, чтобы использовать подходящие типизированные указатели.

+0

Это было мое понимание из верхнего ответа в http: // stackoverflow.com/questions/5450159/type-erasure-methods, которые shared_ptr вызывает правильный деструктор. – Grashlok

+6

@Grashlok Он вызывает правильный деструктор, * если вы скажете, какой из них вызывать *, построив его с указателем на правильный тип. В вашем случае информация о типе теряется до того, как он дойдет до конструктора 'shared_ptr'. –

1

Вы можете использовать шаблон и написать shared_ptr<T>

Если вы не хотите использовать шаблон, то вы должны определить абстрактный класс и все предметы, которые положат в контейнере должны быть выведены из этого класса (как интерфейс Java)

Но я сильно препятствовать вам использовать void*

2

Примечание фронт: Посмотрите на Boost.Any, который, вероятно, делает то, что вы хотите.

При этом вы не можете просто сохранить указатель void в shared_ptr, потому что удаление указателя void не работает. По этой причине shared_ptr перегружает свой конструктор, чтобы создать правильный deleter для фактического типа указателя. Вы могли бы сделать то же самое с помощью конструктора шаблона:

struct Container { 
    int type; 
    std::shared_ptr<void> payload; 
    template<typename T> 
     Container(int t, T* p) : type(t), payload(p) { } 
}; 

Теперь, весело выяснить, почему это рецепт, чтобы выстрелить себе в ногу.