无需返回值时co_return该返回什么?concurrencpp库实现疑问
问题描述
我在自己的库concurrencpp中想要实现make_exceptional_lazy_result函数,功能和C#的Task.FromException方法一致——这个函数会始终抛出异常,永远不会通过co_return返回有效对象。
当前的实现代码如下:
template<class type, class exception_type> lazy_result<type> make_exceptional_lazy_result(exception_type exception) { throw exception; co_return *static_cast<type*>(std::malloc(sizeof(type))); }
我对这种用malloc的取巧写法很不舒服:一方面必须写co_return语句,另一方面程序永远不会执行到这一行。我想知道有没有更好的实现方式?另外我担心返回未初始化本地内存的引用是否符合C++语言规范,而且type不一定支持默认构造,没法直接返回type{}。
优化方案
1. 使用std::declval配合强制转换
利用std::declval生成type类型的纯右值,通过强制转换绕开实际构造需求——由于这行代码永远不会被执行,不会触发对象构造,完全符合语言规范:
template<class type, class exception_type> lazy_result<type> make_exceptional_lazy_result(exception_type exception) { throw exception; co_return static_cast<type&&>(std::declval<type>()); }
std::declval仅用于编译期类型推导,不会生成实际代码,完美适配type无默认构造的场景。
2. 自定义协程Promise逻辑(最优底层方案)
如果lazy_result是你自定义的协程类型,可以直接在Promise类中添加创建异常结果的接口,跳过协程体执行:
template<class type, class exception_type> lazy_result<type> make_exceptional_lazy_result(exception_type exception) { auto promise = std::make_unique<typename lazy_result<type>::promise_type>(); promise->set_exception(std::make_exception_ptr(exception)); return lazy_result<type>(promise->get_return_object()); }
这种方式完全避免冗余的co_return语句,从协程机制根源处理异常结果创建,性能和规范性都最优。
3. 用co_yield占位(仅当lazy_result支持时)
如果lazy_result的协程允许co_yield,可以用它来满足语法要求,不过实用性不如前两种:
template<class type, class exception_type> lazy_result<type> make_exceptional_lazy_result(exception_type exception) { throw exception; co_yield std::declval<type>(); co_return std::declval<type>(); }
原写法的问题说明
你之前用malloc的写法存在合规性问题:std::malloc分配的内存未初始化,解引用后是未构造的对象,即便代码不会执行到这里,也不符合C++对象模型要求——未构造的对象不能被当作有效对象返回,编译器静态分析也可能报错。
内容的提问来源于stack exchange,提问作者David Haim
相关产品推荐
相关产品推荐

