能否在异构集合上用std::all_of/std::ranges::all_of检查shared_ptr初始化?
现代C++实现多类型智能指针的初始化校验(仿Python all()逻辑)
当然可以实现这类泛化逻辑,甚至能做到比你给出的初始化列表方案更简洁、高效的写法,以下是几种可行方案:
方案1:C++17折叠表达式(推荐)
利用C++17引入的折叠表达式,可以直接实现类似Python all() 的泛化校验逻辑,支持任意数量、任意可转换为bool的类型(包括不同类型的std::shared_ptr、std::unique_ptr、普通指针等):
#include <memory> // 泛化校验函数:检查所有传入对象是否都为"有效"(可转换为true) template<typename... Args> constexpr bool all_valid(const Args&... args) noexcept { return (... && static_cast<bool>(args)); } // 原示例代码改造 class A {}; class B {}; class C {}; std::shared_ptr<A> myA; std::shared_ptr<B> myB; std::shared_ptr<C> myC; void foo() { if (!all_valid(myA, myB, myC)) { // 记录日志:存在未初始化的指针 return; } // 执行foo的核心逻辑 }
这个方案的优势:
- 零运行时开销:折叠表达式在编译期展开为逐个校验的逻辑,无需构造临时容器
- 高度泛化:支持任意数量、任意类型的参数,只要该类型能通过
static_cast<bool>判断有效性 - 代码简洁:调用方式和Python的
all()几乎一致,可读性拉满
方案2:你的初始化列表方案(可行但稍逊)
你给出的基于std::ranges::all_of的代码是完全有效的,因为std::shared_ptr<T>可以隐式转换为std::shared_ptr<void>,初始化列表会自动统一类型,lambda中的bool(x)本质是检查智能指针是否非空。不过这个方案需要构造一个临时的std::initializer_list<std::shared_ptr<void>>,相比折叠表达式会有极微小的运行时开销(通常可忽略,但编译期方案更优)。
补充说明
如果你的编译器还不支持C17,也可以用递归模板实现类似的泛化逻辑,但代码会繁琐一些。不过现代C环境(GCC 7+、Clang 5+、MSVC 2017+)都已全面支持折叠表达式,推荐优先使用方案1。
内容的提问来源于stack exchange,提问作者jwm
相关产品推荐
相关产品推荐

