最快的方式 std::vector<Derived> to std::vector<Base>

Fastest Way To std::vector<Derived> to std::vector<Base>

本文关键字:gt lt vector std to Base 方式 Derived      更新时间:2023-10-16

这是测试代码:

class A{};
class B : public A{};
void Test(const std::vector<A>& a)
{
}
int main()
{
    std::vector<A> a;
    std::vector<B> b;
    Test(a);
    Test(b);//Compiler Error
    return 0;
}

由于std::vector<A>std::vector<B>是不同类型的,因此我们无法从一种转换为另一种。

可选方式可以是:

class A{};
class B : public A{};
void Test(const std::vector<A>& a)
{
}
int main()
{
    std::vector<A> a;
    std::vector<B> b;
    Test(a);
    Test(std::vector<A>(b.begin(), b.end()));
    return 0;
}

它起作用,但需要从BA进行额外的复制。如果AB是一个大对象,则可能会非常慢。更好的选择是:

class A{};
class B : public A{};
void Test(const std::vector<A>& a)
{
}
int main()
{
    std::vector<A> a;
    std::vector<B> b;
    Test(a);
    Test(std::vector<A>(std::make_move_iterator(b.begin()), std::make_move_iterator(b.end())));
    return 0;
}

由于它只是移动迭代器而不是整个B类,因此需要更好的性能。但是有一些额外的成本 - 如果b是一个非常大的向量,有大量的项目,迭代也会减慢我的代码速度。

所以我想知道是否有办法直接将std::vector<B>转换为std::vector<A>而无需任何额外费用?

一种方法是使向量成为 Test 函数的模板参数。调用代码将保持不变,无需复制。

#include <vector>
#include <iostream>
class A{
public:
    virtual void print() const {
        std::cout << "A" << std::endl;
    }   
};
class B : public A{
    virtual void print() const {
        std::cout << "B" << std::endl;
    }   
};
template <typename ContainerA>
void Test(const ContainerA& aas)
{
    for(const A& a:aas) {
        a.print();
    }
}
int main()
{
    std::vector<A> a;
    a.push_back(A());
    std::vector<B> b;
    b.push_back(B());
    Test(a);
    Test(b);
    return 0;
}
我不知道

它是否对您有用,但我能想到的最好的方法是将std::vector<Derived>传递给函数并将元素迭代为Base元素。

类似的东西

template <typename D>
void Test (std::vector<D> const & v)
 {
   for ( A const & elem : v )
    {
      // use elem
    }
 }

使用 SFINAE,您只能对Base或从Base元素派生的向量启用Test(),如下所示

template <typename D>
typename std::enable_if<std::is_base_of<A, D>::value>::type
     Test (std::vector<D> const & v)
 {
   for ( A const & elem : v )
    {
      // use elem
    }
 }

所以你有

int main ()
 {
   std::vector<A>   a;
   std::vector<B>   b;
   std::vector<int> c;
   Test(a);    // compile
   Test(b);    // compile
   // Test(c); // compiler error
 }