У меня есть суперкласс, который моделирует Measurement
и два производных класса: PointCloudMeasurement
и ImageMeasurement
.
Другой шаблонный суперкласс, Handler<MeasT>
, определяет интерфейс для обработки измерения.
Два класса обработчиков, PointCloudHandler
и ImageHandler
, специализируются на классе Handler
с соответствующими типами измерений как аргументы шаблона.
Я хотел бы отслеживать все обработчики, используя контейнер указателей на суперкласс, и вызывать соответствующий метод в зависимости от типа производного обработчика под рукой.
Вот code ( link ):
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <memory>
class Measurement {
public:
uint64_t time;
virtual ~Measurement() {}
};
class PointCloudMeasurement : public Measurement {
public:
uint64_t n_points = 64*1024;
};
class ImageMeasurement : public Measurement {
public:
uint64_t n_pixels = 640*480;
};
template<class MeasT = Measurement>
class Handler {
public:
virtual void addMeasurement(MeasT& m) = 0;
};
class PointCloudHandler : public Handler<PointCloudMeasurement> {
public:
void addMeasurement(PointCloudMeasurement& m) override {
std::cout << m.n_points << std::endl;
}
};
class ImageHandler : public Handler<ImageMeasurement> {
void addMeasurement(ImageMeasurement& m) override {
std::cout << m.n_pixels << std::endl;
}
};
int main(void){
std::vector<std::unique_ptr<Handler<Measurement>>> handlers;
handlers.push_back(std::make_unique<PointCloudHandler>());
handlers.push_back(std::make_unique<ImageHandler>());
PointCloudMeasurement pcm;
ImageMeasurement im;
handlers[0]->addMeasurement(pcm);
handlers[1]->addMeasurement(im);
}
что дает мне:
In function 'int main()':
50:59: error: no matching function for call to 'std::vector<std::unique_ptr<Handler<Measurement> > >::push_back(std::_MakeUniq<PointCloudHandler>::__single_object)'
50:59: note: candidates are:
In file included from /usr/include/c++/4.9/vector:64:0,
from 4:
/usr/include/c++/4.9/bits/stl_vector.h:913:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::unique_ptr<Handler<Measurement> >; _Alloc = std::allocator<std::unique_ptr<Handler<Measurement> > >; std::vector<_Tp, _Alloc>::value_type = std::unique_ptr<Handler<Measurement> >]
push_back(const value_type& __x)
^
/usr/include/c++/4.9/bits/stl_vector.h:913:7: note: no known conversion for argument 1 from 'std::_MakeUniq<PointCloudHandler>::__single_object {aka std::unique_ptr<PointCloudHandler, std::default_delete<PointCloudHandler> >}' to 'const value_type& {aka const std::unique_ptr<Handler<Measurement> >&}'
/usr/include/c++/4.9/bits/stl_vector.h:931:7: note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::unique_ptr<Handler<Measurement> >; _Alloc = std::allocator<std::unique_ptr<Handler<Measurement> > >; std::vector<_Tp, _Alloc>::value_type = std::unique_ptr<Handler<Measurement> >]
push_back(value_type&& __x)
^
/usr/include/c++/4.9/bits/stl_vector.h:931:7: note: no known conversion for argument 1 from 'std::_MakeUniq<PointCloudHandler>::__single_object {aka std::unique_ptr<PointCloudHandler, std::default_delete<PointCloudHandler> >}' to 'std::vector<std::unique_ptr<Handler<Measurement> > >::value_type&& {aka std::unique_ptr<Handler<Measurement> >&&}'
51:54: error: no matching function for call to 'std::vector<std::unique_ptr<Handler<Measurement> > >::push_back(std::_MakeUniq<ImageHandler>::__single_object)'
51:54: note: candidates are:
In file included from /usr/include/c++/4.9/vector:64:0,
from 4:
/usr/include/c++/4.9/bits/stl_vector.h:913:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::unique_ptr<Handler<Measurement> >; _Alloc = std::allocator<std::unique_ptr<Handler<Measurement> > >; std::vector<_Tp, _Alloc>::value_type = std::unique_ptr<Handler<Measurement> >]
push_back(const value_type& __x)
^
/usr/include/c++/4.9/bits/stl_vector.h:913:7: note: no known conversion for argument 1 from 'std::_MakeUniq<ImageHandler>::__single_object {aka std::unique_ptr<ImageHandler, std::default_delete<ImageHandler> >}' to 'const value_type& {aka const std::unique_ptr<Handler<Measurement> >&}'
/usr/include/c++/4.9/bits/stl_vector.h:931:7: note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::unique_ptr<Handler<Measurement> >; _Alloc = std::allocator<std::unique_ptr<Handler<Measurement> > >; std::vector<_Tp, _Alloc>::value_type = std::unique_ptr<Handler<Measurement> >]
push_back(value_type&& __x)
^
/usr/include/c++/4.9/bits/stl_vector.h:931:7: note: no known conversion for argument 1 from 'std::_MakeUniq<ImageHandler>::__single_object {aka std::unique_ptr<ImageHandler, std::default_delete<ImageHandler> >}' to 'std::vector<std::unique_ptr<Handler<Measurement> > >::value_type&& {aka std::unique_ptr<Handler<Measurement> >&&}'
Я не понимаю, почему преобразование указателя не работает, поскольку все производные классы наследуются от Handler<MeasT>
, где MeasT
является производным от Measurement
.
Я встречал похожие вопросы, но большинство из них сохраняют шаблон даже в производном классе (чего у меня нет) или обратитесь к CRTP. Однако CRTP напрямую использует производный класс в качестве аргумента шаблона, а здесь я использую другой производный класс.