如何解决BOOST_OUTCOME_TRY适配llvm::ErrorOr<T>的编译错误?
问题分析与解决方法
编译失败的核心原因
- 函数名不匹配:Boost Outcome要求的失败分支处理函数是
try_operation_return_as,但你定义的是try_return_as(缺少operation_前缀),导致宏扩展时找不到对应函数。 - 错误的错误访问方式:你在
try_return_as中使用v->getError(),但v->仅在ErrorOr有值时有效,失败时应该调用v.getError()来获取错误对象,否则会触发未定义行为。 - 模板范围过窄:你的模板仅针对
llvm::ErrorOr<std::unique_ptr<T>>,无法复用给其他ErrorOr类型,且函数实现存在路径无返回值的问题(当v有值时,函数没有返回值,违反C++语法)。
修正后的代码实现
#include <llvm/Support/MemoryBuffer.h> #include <boost/outcome.hpp> namespace outcome = BOOST_OUTCOME_V2_NAMESPACE; BOOST_OUTCOME_V2_NAMESPACE_BEGIN // 泛化处理所有llvm::ErrorOr<T>类型 template<class T> inline bool try_operation_has_value(const llvm::ErrorOr<T>& v) { return static_cast<bool>(v); } template<class T> inline auto try_operation_return_as(const llvm::ErrorOr<T>& v) { // 仅在try_operation_has_value返回false时被调用,直接返回错误 return outcome::failure(v.getError()); } template<class T> inline auto try_operation_extract_value(const llvm::ErrorOr<T>& v) { // 返回ErrorOr内部的有效值,保持原类型(比如std::unique_ptr<T>) return *v; } BOOST_OUTCOME_V2_NAMESPACE_END int test_stdin() { BOOST_OUTCOME_TRY(const auto& ibuff, llvm::MemoryBuffer::getSTDIN()); // 这里可以正常使用ibuff,类型为const std::unique_ptr<llvm::MemoryBuffer>& return 0; }
关键修正点说明
- 函数名修正:将
try_return_as改为try_operation_return_as,匹配Boost Outcome的宏扩展要求。 - 错误访问修正:用
v.getError()替代v->getError(),确保失败时安全获取错误对象。 - 模板泛化:将模板参数改为
llvm::ErrorOr<T>,支持所有ErrorOr包装的类型,包括std::unique_ptr<T>、基础类型等,提升复用性。 - 返回值完整性:
try_operation_return_as仅在失败分支被调用,直接返回failure对象,避免无返回值的语法错误;try_operation_extract_value直接返回*v,保留原对象的类型和所有权语义。
内容的提问来源于stack exchange,提问作者Sean Champ
相关产品推荐
相关产品推荐

