Question

I have a std::vector of Boost shared pointers to objects, and would like to get a vector of shared pointers to the same objects casted down to a more specific type:

//using boost::shared_ptr, std::vector;
vector<shared_ptr<A> > originalVec;
vector<shared_ptr<B> > targetVec( originalVec.size() ); // B extends A

For a single element shared_ptr<A> elem, it is possible to cast it using boost::static_pointer_cast<B>(elem), whose syntax is reproduced below (from Boost shared_ptr doc):

template<class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws

I don't know how to use it with std::transform. Mi tries include:

//using boost::bind, boost::static_pointer_cast
transform( originalVec.begin(), originalVec.end(), targetVec.begin(), bind( static_pointer_cast<B>, _1) )
transform( originalVec.begin(), originalVec.end(), targetVec.begin(), bind( static_pointer_cast<B,A>, _1) ) 

Getting in both cases a "no matching function for call to bind(<unresolved overloaded function type>, boost::arg<1>& )"

Any ideas?


EDIT: The problem could be related with an ambiguity, since a similar function template is defined for intrusive pointer class, with syntax:

template<class T, class U>
intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws

The question, in this case, is how to specify the type of the first argument so that the compiler knows which method to select.

Était-ce utile?

La solution

You can usually tell the compiler which overload you want by specifying the type of the function pointer you want e.g.

typedef shared_ptr<B>(*func_type)(const shared_ptr<A>&);

transform( originalVec.begin(), originalVec.end(), targetVec.begin(), bind( (func_type)static_pointer_cast<B,A>, _1) );

But in cases where you get this sort of error from an overloaded function that can't be disambiguated, my preferred solution is often to provide a custom functor that does the call, so that overload resolution is done by the compiler, and you don't have to select an overload e.g.

struct Downcast {
  shared_ptr<B> operator()(const shared_ptr<A>& p) const
  { return shared_pointer_cast<B>(p); }
};

transform( originalVec.begin(), originalVec.end(), targetVec.begin(), Downcast() );

Autres conseils

I'm not sure why you got that error with your second try, because that one should've worked.

However, there is a possibility you'll overrun the bounds of targetVec if it is empty because simply passing an iterator to transform is not enough, you need to push_back the result of the cast into targetVec. This can be done easily by passing a back_insert_iterator to transform.

int main()
{
    std::vector<boost::shared_ptr<A>> original;
    std::vector<boost::shared_ptr<B>> target;

    original.push_back( boost::make_shared<B>() );

    boost::transform( original,
                      std::back_inserter( target ),
                      boost::bind( boost::static_pointer_cast<B, A>, _1 ) );

    // OR
    std::transform( original.begin(), 
                    original.end(),
                    std::back_inserter( target ),
                    boost::bind( boost::static_pointer_cast<B, A>, _1 ) );
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top