c ++ std :: copy类型转换为派生类可能吗?

mok*_*oka 11 c++ copy list vector

我很确定没有办法明确地做到这一点,但我想问一下,如果有更好的方法.我有一个基类A和一个派生类B,现在我有一个指向B*的st*:: A*列表,我想将这个A*列表复制到一个std :: vector of B*基本上我想这样做:

std::list<A*> aList = someObject.getAs();
std::vector<B*> bVec = std::vector<B*>(aList.begin(), aList.end());
Run Code Online (Sandbox Code Playgroud)

我很确定当列表和向量是相同类型时(例如两者都是A*),这应该编译,但因为在这种情况下A*是B*的基类我不能这样做,因为我必须明确地进行类型转换,例如:

std::list<A*> aList = someObject.getAs();
std::vector<B*> bVec;
bVec.reserve(aList.size());
std::list<A*>::iterator it = aList.begin();
for(it; it!=aList.end(); ++it)
{
   B* b = static_cast<B*>(*it);
   bVec.push_back(b);
}
Run Code Online (Sandbox Code Playgroud)

有没有比我的第二种方法更优雅的方式,还是我必须这样做?

Mik*_*our 16

隐式转换是不安全的,所以你必须明确它.将某种转换应用于序列的标准算法是std::transform,您可以使用它来填充空容器,如下所示:

struct A {};
struct B : A {};

template <typename From, typename To>
struct static_caster
{
    To* operator()(From* p) {return static_cast<To*>(p);}
};

std::list<A*> a;
std::vector<B*> b;
std::transform(a.begin(), a.end(), std::back_inserter(b), static_caster<A,B>());
Run Code Online (Sandbox Code Playgroud)


Tro*_*our 7

定义一个仿函数来进行投射,例如.

struct Downcast
{
    B* operator() ( A* a ) const
    {
        return static_cast< B* >( a );
    }
};
Run Code Online (Sandbox Code Playgroud)

然后使用std::transform而不是std::copyie

bVec.resize(aList.size());
std::transform( aList.begin(), aList.end(), bVec.begin(), Downcast() );
Run Code Online (Sandbox Code Playgroud)

请注意,您也可以这样做

std::vector<B*> bVec;
std::transform( aList.begin(), aList.end(), std::back_inserter( bVec ), Downcast() );
Run Code Online (Sandbox Code Playgroud)

在这种情况下bVec会根据需要增长,但我更喜欢第一种方法,绝对确保内存分配一次完成.正如@Mike Seymour指出的那样你可以bVec.reserve( aList.size() )在第二种情况下调用以确保一次分配.