gpt4 book ai didi

c++ - 统一迭代 std::vector 和 std::vector>

转载 作者:行者123 更新时间:2023-11-28 01:45:34 25 4
gpt4 key购买 nike

我经常遇到这样的情况,我引入了一个抽象基类(称为 Foo )来将不同子类的实例(称为 BarBaz )存储在容器中(例如 std::vector<std::unique_ptr<Foo>> ) .为了便于说明,让我将这些示例类放在这里:

class Foo {
public:
virtual int getId() const = 0;
};

class Bar : public Foo {
public:
Bar(int id) : id_(id) {}
int getId() const override { return id_; }
private:
int id_;
};

class Baz : public Foo {
public:
Baz(int id) : id_(id) {}
int getId() const override { return id_; }
private:
int id_;
};

如果我实现一个函数来遍历 std::vector<std::unique_ptr<Foo>> , 看起来像

template<class InputIterator>
void printIds(InputIterator first, InputIterator last) {
for (; first != last; ++first)
std::cout << (*first)->getId() << std::endl;
}

但是,如果我还想允许迭代homogeneous 类型的 vector (例如 std::vector<Bar> )而不重写整个函数(或可能的其他类似类型的函数)怎么办?我看到两种明显的可能性:

1)实现功能

template<class Type>
const Type & dereference(const Type &value) {
return value;
}

template<class Type>
const Type & dereference(const std::unique_ptr<Type> &value) {
return *value;
}

并替换

std::cout << (*first)->getId() << std::endl;

通过

std::cout << dereference(*first).getId() << std::endl;

2)实现功能

template<class Type>
int getId(const Type &value) {
return value.getId();
}

template<class Type>
int getId(const std::unique_ptr<Type> &value) {
return value->getId();
}

并替换

std::cout << (*first)->getId() << std::endl;

通过

std::cout << getId(*first) << std::endl;

选项 1) 似乎是处理 Type & 类型引用的一般可能性(或 const Type & )和 std::unique_ptr<Type> (甚至 Type *const Type * )统一。但是,我还没有看到它在生产代码中被大量使用。这是避免代码重复的常见模式吗?或者有更好的方法来处理这个问题吗?

最佳答案

我会写 get_ptr<T> .

get_ptr<T*>如果失败则返回 nullptr。

如果传递了对可转换为 T* 的内容的引用, 它返回它。

如果传递了对可转换为 T& 的内容的引用, 它返回一个指向它的指针。

否则,如果传递一个指针,如果指针为 null 则返回 null 并且 get_ptr<T>(*ptr)如果指针不为空。

否则,如果x.get()返回一个指针,它返回 get_ptr<T>(x.get()) .

现在printIds阅读:

template<class InputIterator>
void printIds(InputIterator first, InputIterator last) {
for (; first != last; ++first)
std::cout << get_ptr<Foo>(*first)->getId() << std::endl;
}

请注意 get_ptr 的可能性失败在这里相当明显。


如果你不想硬编码类型 T ,我们可以更进一步。

如果get_obj_ptr传递一个指向指针的指针,并且指针不为空,它取消引用指针并递归。如果为 null,则返回转换为相同类型的 nullptr。

如果通过了谁的类(class).get()返回一个指针,它在 get_obj_ptr(x.get()) 上递归.

否则,如果get_obj_ptr(x)传递一个指针,它返回 x .

否则,如果get_obj_ptr(x)传递一个左值,它返回 std::addressof(x) .

与您的代码不同,它承认失败的可能性。

template<class InputIterator>
void printIds(InputIterator first, InputIterator last) {
for (; first != last; ++first)
auto* ptr = get_obj_ptr(*first);
if (ptr)
std::cout << ptr->getId() << std::endl;
else
std::cout << "null object" << std::endl;
}

作为一般规则,采用智能指针并假设它们永远不会为 null 是一个坏主意。

关于c++ - 统一迭代 std::vector<T> 和 std::vector<unique_ptr<T>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45286632/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com