从子类的STL向量转换为基类的向量

时间:2021-10-30 21:20:28

I am wondering if it is possible to convert a vector of derived class values to a vector of base class values. Specifically I want to be able to pass a vector of base class objects to a function whose formal parameters takes a vector of base class. It does not appear to be possible directly as the following code example produces an error (using g++):

我想知道是否有可能将派生类值的向量转换为基类值的向量。具体地说,我希望能够将基类对象的向量传递给一个函数,该函数的形式参数采用基类的向量。这似乎不可能直接实现,因为下面的代码示例会产生错误(使用g++):

#include <vector>

class A {
};

class B : public A {
};


void function(std::vector<A> objs) {
}

int main(int argc, char **argv) {
    std::vector<B> objs_b;
    objs_b.push_back(B());
    function(objs_b);
}

test.cc:16: error: conversion from ‘std::vector<B, std::allocator<B> >’ to non-scalar type ‘std::vector<A, std::allocator<A> >’ requested

测试。cc:16: error:从' std::vector > '转换为非标量类型' std::vector > '请求的 ,> ,>

I would like to be able to be able to call function without having to define a new vector with elements of type A, inserting my elements of type B or changing to a vector of pointers.

我希望能够调用函数,而不需要定义带有a类型元素的新向量,插入类型B的元素,或者更改为指针的向量。

2 个解决方案

#1


11  

No, it is not. vector<B> is not derived from vector<A>, regardless of the fact that B is derived from A. You will have to change your function somehow.

不,它不是。向量不是由向量推导出来的,不管B是由A推导出来的,你必须以某种方式改变你的函数。

A more idiomatically C++ approach might be to template it and have it take a pair of iterators - this is why the various standard library functions (<algorithm> etc) work that way, because it separates the implementation of the algorithm from the kind of thing it's operating on.

更习惯地说,c++方法可能是对它进行模板化,并让它使用一对迭代器——这就是为什么各种标准库函数( 等)都是这样工作的,因为它将算法的实现与它所操作的对象分离开来。

#2


3  

Sometimes there are ways around this. Take a loot at Boost and some of the template meta-programming packages they have or use. Specifically I'd look at is_base_of for these kinds of purposes combined with partial template specialization.

有时候有很多方法可以解决这个问题。看看Boost和他们所拥有或使用的一些模板元编程包。具体地说,我将考虑is_base_of与部分模板专门化结合使用。

For instance, if you wish to do some template magic trickery:

例如,如果你想做一些模板魔术:

template<typename T, bool Allowed>
struct TemplateVectorCode;

You make a forward declaration of a templated class. Then you make a specialization with a "true" boolean value:

您要对模板类做一个转发声明。然后用“真”布尔值进行专门化:

template<typename T> struct TemplateVectorCode<T, true>{
    void operator(const std::vector<T>& myVector) const{ //definition in here }
};

Finally you use that with is_base_of to only instantiate instances of your template functor in the following manner:

最后,使用is_base_of来实例化模板函子的实例,方法如下:

template<typename T, typename Base>
struct MyFunction : TemplateVectorCode<T, boost::is_base_of<Base,T>::value>{
};

The important point to note is that since we have not defined a TemplateVectorCode<T, false> the compiler will throw a compile error if you attempt to use your functor with a class type T that does not derive from the type V. That means you can work with the same code in one place without having to write multiple versions of it.

重点要注意的是,由于我们没有定义TemplateVectorCode < T,假>编译器将抛出一个编译错误如果你试图使用函子的类类型T并不来自类型v .这意味着你可以在一个地方使用相同的代码,而不必编写多个版本。

(if I screwed up the partial template specialization, someone please edit it. I need to go to bed.)

(如果我搞砸了部分模板专门化,请有人编辑它。我得去睡觉了。

#1


11  

No, it is not. vector<B> is not derived from vector<A>, regardless of the fact that B is derived from A. You will have to change your function somehow.

不,它不是。向量不是由向量推导出来的,不管B是由A推导出来的,你必须以某种方式改变你的函数。

A more idiomatically C++ approach might be to template it and have it take a pair of iterators - this is why the various standard library functions (<algorithm> etc) work that way, because it separates the implementation of the algorithm from the kind of thing it's operating on.

更习惯地说,c++方法可能是对它进行模板化,并让它使用一对迭代器——这就是为什么各种标准库函数( 等)都是这样工作的,因为它将算法的实现与它所操作的对象分离开来。

#2


3  

Sometimes there are ways around this. Take a loot at Boost and some of the template meta-programming packages they have or use. Specifically I'd look at is_base_of for these kinds of purposes combined with partial template specialization.

有时候有很多方法可以解决这个问题。看看Boost和他们所拥有或使用的一些模板元编程包。具体地说,我将考虑is_base_of与部分模板专门化结合使用。

For instance, if you wish to do some template magic trickery:

例如,如果你想做一些模板魔术:

template<typename T, bool Allowed>
struct TemplateVectorCode;

You make a forward declaration of a templated class. Then you make a specialization with a "true" boolean value:

您要对模板类做一个转发声明。然后用“真”布尔值进行专门化:

template<typename T> struct TemplateVectorCode<T, true>{
    void operator(const std::vector<T>& myVector) const{ //definition in here }
};

Finally you use that with is_base_of to only instantiate instances of your template functor in the following manner:

最后,使用is_base_of来实例化模板函子的实例,方法如下:

template<typename T, typename Base>
struct MyFunction : TemplateVectorCode<T, boost::is_base_of<Base,T>::value>{
};

The important point to note is that since we have not defined a TemplateVectorCode<T, false> the compiler will throw a compile error if you attempt to use your functor with a class type T that does not derive from the type V. That means you can work with the same code in one place without having to write multiple versions of it.

重点要注意的是,由于我们没有定义TemplateVectorCode < T,假>编译器将抛出一个编译错误如果你试图使用函子的类类型T并不来自类型v .这意味着你可以在一个地方使用相同的代码,而不必编写多个版本。

(if I screwed up the partial template specialization, someone please edit it. I need to go to bed.)

(如果我搞砸了部分模板专门化,请有人编辑它。我得去睡觉了。