将std::vector转换为项超类的vector



我有两个类,类Subclass继承自类Superclass:

class Superclass { /* … */ };
class Subclass : public Superclass { /* … */ };

在代码的某个地方,我还有一个向量Subclass *。我需要使用向量,因为我想避免列表结构的另一个分配,并且向量是由其他函数返回的:

std::vector<Subclass *> &myVector = getMyVector();

我还有一个函数,我们称之为printSuperclasses,它接受一个类型为std::vector<Superclass *> &的参数。如何将上面显示的向量传递给函数?使用static_cast不起作用,我希望避免使用reinterpret_cast

void printSuperclasses(std::vector<Superclass *> const &);
//                     ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
//                          or another type?

如果我理解正确,Superclass *Subclass *的两个向量在内存中应该以相同的方式表示(它们是吗?(,所以我应该能够从后面的转换为第一个。有没有一种方法可以在C++中安全地?函数是否应该不将其作为向量接收,而是作为不同的东西(迭代器等(接收?

不能安全地将std::vector<Subclass *>传递给采用std::vector<Superclass *> &的函数。

如果它做了以下操作呢?

class Other : public Superclass {};
void takesSuperclass(std::vector<Superclass *> & vec)
{
vec.push_back(new Other);
}

现在你可能会想,但我的函数不能做到这一点。你可能是对的,但你没有告诉类型系统。

如果你想把各种各样的指针传递给takesSuperclass,那么你可以把它做成一个模板

template<typename Supers>
auto takesSuperClass(Supers && supers)

在C++20中,您可以合理地执行这些要求

template<typename T>
using ptr_element_t = typename std::pointer_traits<T>::element_type;
template<typename Derived, typename Base>
concept derived_ptr = std::derived_from<ptr_element_t<Derived>, ptr_element_t<Base>>;
template<std::ranges::range Range>
requires derived_ptr<std::ranges::range_value_t<Range>, Super *>
auto takesSuperClass(Range supers) 

如果你不想有一个模板,你也可以做一些类型擦除,例如boost::any_range

void takesSuperclass(boost::any_range<Super *, boost::forward_traversal_tag> supers)

如果您不想更改函数printSuperclasses的签名,我建议您执行以下操作。编写一个包装函数,它将迭代器作为参数,然后在该函数中构造一个向量,稍后将传递给您提到的函数。这可以像一样完成

template<class Iter>
void printSuperclasses(Iter first, Iter last)
{
std::vector<Superclass*> superclass_vec(first, last);
printSuperclasses(superclass_vec);
}

如果IterSuperclass的任何子类的指针向量的迭代器,则函数将能够转换指针。

函数的调用方式如下。

std::vector<Subclass*> subclass_vec;  // not initialized, but it is not important in the case of example.
printSuperclasses(subclass_vec.begin(), subclass_vec.end());

最新更新