[英]C++ Passing std::vector< boost::shared_ptr< foo > >
[英]convert vector<boost::shared_ptr<Foo> > to vector<Foo*> , is it possible?
我有一个函数,将指向Foo的指针的stl向量作为参数。
但是,我也有一些对象,它们是指向同一类Foo的共享指针。 我也希望能够调用此函数来提供其他对象。 我是否需要重载该功能? 我似乎无法将其从vector<shared_ptr<Foo>>
动态vector<shared_ptr<Foo>>
到vector<Foo*>
。
我知道可以使用Get()方法将shared_ptr转换为指针,但是那又如何呢? 有任何想法吗?
有关问题的更新 :
我已经实现了下面建议的解决方案,但是现在,当声明模板函数的所有可能类型时,我得到:
“'void my_func(std :: vector&,std :: vector&)[带有Ptr_Jet1 = Jet *,Ptr_Jet2 = Jet *]的显式实例”,但没有可用的定义”
对于所有其他组合都相同(例如,Ptr_Jet1是shared_ptr而不是Jet *。
在.cpp文件上,我有:
template<typename Ptr_Jet1, typename Ptr_Jet2>
void my_func(vector<Ptr_Jet1> vec1, vector<Ptr_Jet2> vec2){
//definition
}
在.h文件中,我有:
typedef boost::shared_ptr<Jet> ptr_jet;
template<typename Ptr_Jet1, typename Ptr_Jet2>
void my_func(vector<Ptr_Jet1> vec1, vector<Ptr_Jet2> vec2);
//
template void my_func(vector<Jet*> vec1, vector<Jet*> vec2);
template void my_func(vector<Jet*> vec1, vector<ptr_jet> vec2);
template void my_func(vector<ptr_jet> vec1, vector<Jet*> vec2);
template void my_func(vector<ptr_jet> vec1, vector<ptr_jet> vec2);
我不明白这是怎么回事...
shared_ptr<T>
和T*
是不同的类型,因此您不能简单地从vector<shared_ptr<T>>
为vector<T*>
。 如果确实需要vector<T*>
(这意味着您无法按照Barnabas Szabolcs的回答更改函数),则需要手动将指针从源向量中复制出来。 因为无论如何您都在使用boost,所以我认为使用Boost.Range
是可以的。 如果可以使用C ++ 11,这很简单:
vector< shared_ptr<Foo> > foo;
auto range = foo | boost::adaptors::transform([](shared_ptr<Foo>& ptr) { return ptr.get(); };
std::vector<Foo*> bar(range.begin(), range.end());
这将C ++ 11用于lambda函数(可以很容易地用functor / functionptr替换c ++ 03代码)并auto
保存范围。 IIRC在Boost.Range
的文档中未指定范围转换的返回类型,因此硬编码可能不是一个好主意。 要摆脱c ++ 03代码中的auto
,可以使用boost::copy_range
:
struct transformation //using a functor instead of a plain function will enable inlining of the transformation, which is liekly benefitial for performance
{ Foo* operator()(shared_ptr<Foo>& ptr) { return ptr.get();}};
std::vector<Foo*> bar = boost::copy_range<std::vector<Foo*>>(foo | boost::adaptors::transform(transformation()));
当然,您可以改用Boost.Iterators
的transform_iterator
,但是我发现使用Range
使代码更易读。
当然,如果仅将vector<Foo*>
用作函数的参数,则可以跳过将其写入变量的操作,而直接调用myFunc(copy_range<std::vector<Foo*>>(...))
,这可能会使编译器跳过一些副本。
如果您编写了该函数, 我建议您进行模板化 ,因为shared_ptr具有operator*
,就像您使用原始指针一样。
template<typename _Tp_ptr_Foo>
void your_fun(const vector<_Tp_ptr_Foo>& ); // or something alike here
在这种情况下,模板化实际上与函数重载相同,但是通过模板化,您可以避免重复代码。
如果您无法控制该功能,则需要转换整个矢量。 如果它不超过1000个元素,并且您执行的次数不超过数百次,那么就不会有太多性能损失。
不幸的是,您不能动态地将它们彼此转换,因为它们与继承无关。 尽管它们看起来相似,但vector<T>
与vector<U>
无关。
更新:
我同意Grizzly的观点,模板参数是自动推断出来的,因此您无需明确地写出来。 因此,您可以继续将其your_fun(v)
。
唯一需要注意的是:如果分别处理头文件和代码文件,则需要明确指示编译器应创建两个函数 ,如下所示:
//header file:
template<typename _Tp_ptr_Foo>
void your_fun(const vector<_Tp_ptr_Foo>& );
template void your_fun(const vector<Foo*>& );
template void your_fun(const vector<shared_ptr<Foo> >& );
//code file:
template<typename _Tp_ptr_Foo>
void your_fun(const vector<_Tp_ptr_Foo>& )
{
// implementation
}
UPDATE2 :(回答Elelias的评论)
您的模板声明应如下所示:
// header file:
template<typename _Tp1, typename _Tp2, typename _Tp3>
void your_fun(const vector<_Tp1>&, const vector<_Tp2>&, const vector<_Tp3>& );
之后,您有2个选项:
您可以将定义放入单独的代码文件中。 在这种情况下, 实现文件中的标头需要6个显式模板实例,每个组合一个。
您可以将定义放入标头中 ,然后不需要6个显式实例化。 在这种情况下,我宁愿建议这样做。 尽管它没有将声明和实现分开,但它并不是一个糟糕的解决方案。 我在严肃的c ++库中也看到了这种方法,例如,您可以查看OpenCV中的operation.hpp。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.