繁体   English   中英

转换向量 <boost::shared_ptr<Foo> &gt;到矢量 <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.Iteratorstransform_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个选项:

  1. 您可以将定义放入单独的代码文件中。 在这种情况下, 实现文件中的标头需要6个显式模板实例,每个组合一个。

  2. 您可以将定义放入标头中 ,然后不需要6个显式实例化。 在这种情况下,我宁愿建议这样做。 尽管它没有将声明和实现分开,但它并不是一个糟糕的解决方案。 我在严肃的c ++库中也看到了这种方法,例如,您可以查看OpenCV中的operation.hpp。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM