undu
undu

Reputation: 2519

passing vector<shared_ptr<Derived>> to a function expecting vector<shared_ptr<Base>>

I'm facing a problem with the code structure I use, which is as follows (simplified) :

class SPoint
{
public:
    SPoint(double x, double y, double z) : _x(x), _y(y), _z(z) {}

protected:
    double _x, _y, _z;
}

class Point3D : public SPoint
{
public:
    Point3D(double x, double y, double z) : SPoint(x, y, z) { // default values for U and V }

protected:
    double U, V;
}

These points are use to create polylines :

class SPolyline
{
public:
    SPolyline(const vector<shared_ptr<SPoint>>& points) { // points are cloned into _points}

protected:
    vector<shared_ptr<SPoint>> _points;
};


class Polyline3D : SPolyline
{
public :
    Polyline3D(const vector<shared_ptr<Point3D>>& points) : SPolyline(points)  // doesn't compile
};

VS2010 rejects me when I try to compile Polyline3D with this error

error C2664: 'SPolyline::SPolyline(const std::vector<_Ty> &)' : cannot convert parameter 1 from 'const std::vector<_Ty>' to 'const std::vector<_Ty> &'
with
[
  _Ty=std::tr1::shared_ptr<SPoint>
]
and
[
  _Ty=std::tr1::shared_ptr<Point3D>
]
and
[
  _Ty=std::tr1::shared_ptr<SPoint>
]
Reason: cannot convert from 'const std::vector<_Ty>' to 'const std::vector<_Ty>'
with
[
  _Ty=std::tr1::shared_ptr<Point3D>
]
and
[
  _Ty=std::tr1::shared_ptr<SPoint>
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

There's no default conversion from vector<shared_ptr<Derived>> to vector<shared_ptr<Base>>. How can this problem be resolved, knowing that I need shared ownership for the points in the polylines ? The shared_ptr I use are standard ones, not from Boost.

Upvotes: 5

Views: 1195

Answers (2)

Mr.Anubis
Mr.Anubis

Reputation: 5342

Another thing you could do is :

class Polyline3D : public SPolyline
{
public :
    Polyline3D(const vector<shared_ptr<Point3D>>& points) : SPolyline(std::vector<shared_ptr<SPoint> >(points.begin(), points.end())){}  
};

Upvotes: 0

pmr
pmr

Reputation: 59831

Abstract away from your container and use iterators.

template<typename InputIterator>
Polyline3D(InputIterator begin, IntputIterator end) : SPolyline(begin ,end) {}

It is possible to implement such a conversion for vector, but given the subtle mishaps that it can introduce (think implict conversions) not having it is probably better.

Upvotes: 5

Related Questions