C++20风格下std::vector<shared_ptr<Base>>转vector<shared_ptr<Derived>>方法
前提类定义
class Base { }; class Derived : public Base { };
现有存储基类智能指针的容器:
std::vector<std::shared_ptr<Base>> baseVec;
需要转换为存储派生类智能指针的容器:
std::vector<std::shared_ptr<Derived>> derivedVec;
两种转换方案(C++20风格)
方案1:无类型检查(确保所有元素都是Derived实例)
如果能100%确定baseVec中的每个shared_ptr<Base>都指向Derived对象,可以用static_pointer_cast配合C++20范围特性快速转换:
写法1:构造函数直接传入转换逻辑
#include <vector> #include <memory> std::vector<std::shared_ptr<Derived>> derivedVec( baseVec.begin(), baseVec.end(), [](const std::shared_ptr<Base>& ptr) { return std::static_pointer_cast<Derived>(ptr); } );
写法2:用std::views::transform生成视图再构造
#include <vector> #include <memory> #include <ranges> auto derived_view = baseVec | std::views::transform( [](auto&& ptr) { return std::static_pointer_cast<Derived>(std::forward<decltype(ptr)>(ptr)); } ); std::vector<std::shared_ptr<Derived>> derivedVec(derived_view.begin(), derived_view.end());
注意:此方式无类型校验,若存在非
Derived的子类实例,会触发未定义行为,仅在场景明确时使用。
方案2:类型安全转换(过滤无效元素)
如果baseVec中可能混有其他Base子类实例,必须用dynamic_pointer_cast做类型检查,并过滤转换失败的空指针:
标准写法
#include <vector> #include <memory> #include <ranges> auto filtered_view = baseVec | std::views::transform( [](auto&& ptr) { return std::dynamic_pointer_cast<Derived>(std::forward<decltype(ptr)>(ptr)); } ) | std::views::filter( [](const auto& ptr) { return ptr != nullptr; } ); std::vector<std::shared_ptr<Derived>> derivedVec(filtered_view.begin(), filtered_view.end());
简化写法(利用std::identity)
C++20的std::identity可以直接过滤空指针(需包含<functional>):
#include <vector> #include <memory> #include <ranges> #include <functional> std::vector<std::shared_ptr<Derived>> derivedVec( baseVec | std::views::transform( [](auto&& ptr) { return std::dynamic_pointer_cast<Derived>(std::forward<decltype(ptr)>(ptr)); } ) | std::views::filter(std::identity{}) );
此方案会自动跳过无法转换为Derived的元素,最终derivedVec仅包含有效的Derived智能指针。
内容的提问来源于stack exchange,提问作者Jan Hackenberg
相关产品推荐
相关产品推荐

