coroutine_handle是否支持多态promise?from_promise等方法兼容性问询
C++协程
coroutine_handle::from_promise与from_address的特化Promise兼容性问题 问题翻译
我特指from_promise方法,想知道:若尝试从SpecialisedPromise引用获取coroutine_handle,该函数能否正确且可移植地工作?from_address方法也存在类似疑问。另外附上代码示例,请问该程序是否能按预期运行?通过不同类型的coroutine_handle访问是否存在潜在bug或未定义行为?
核心答案
from_promise可以正确且可移植地从SpecialisedPromise引用获取对应协程句柄,只要该Promise是协程实际绑定的类型。from_address同样安全可用,前提是传入的地址确实属于某个协程的Promise实例,且句柄的模板类型与该Promise类型完全匹配。- 只要代码符合标准约束,程序就能按预期运行;错误使用不同类型的
coroutine_handle会触发未定义行为。
详细解释
根据C++标准,coroutine_handle<P>::from_promise(P& p)的设计目标就是从协程关联的Promise实例获取对应句柄。无论Promise是通用类型还是自定义的SpecialisedPromise,只要传入的p是当前协程的有效Promise对象,调用该方法就能得到正确的coroutine_handle<SpecialisedPromise>,这种用法完全符合标准,具备跨平台可移植性。
对于from_address,coroutine_handle<P>::from_address(void* addr)要求传入的地址必须是某个协程Promise对象的有效地址,且模板参数P必须与该Promise的实际类型一致。满足这两个条件时,构造出的句柄是合法的,不存在未定义行为。
代码示例分析(假设示例如下)
假设你的代码结构类似:
#include <coroutine> #include <iostream> // 自定义特化Promise struct SpecialisedPromise { struct promise_type { SpecialisedPromise get_return_object() { return {}; } std::suspend_never initial_suspend() { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() {} }; }; // 返回特化Promise的协程 SpecialisedPromise my_coroutine() { co_return; } int main() { auto coro_obj = my_coroutine(); // 通过地址获取句柄,再拿到Promise引用,最后用from_promise构造句柄 auto handle = std::coroutine_handle<SpecialisedPromise::promise_type>::from_address(&coro_obj); auto& promise_ref = handle.promise(); auto another_handle = std::coroutine_handle<SpecialisedPromise::promise_type>::from_promise(promise_ref); // 验证句柄有效性 std::cout << std::boolalpha << handle.done() << "\n"; // 输出true handle.destroy(); return 0; }
这个程序可以按预期运行,关键要保证:
coroutine_handle的模板参数与协程的promise_type完全一致;- 传递给
from_promise的引用是协程关联的有效Promise实例; - 传递给
from_address的地址是Promise对象的有效地址,且对象生命周期未结束。
潜在风险与注意事项
- 类型不匹配的风险:如果用
coroutine_handle<OtherPromise>去绑定SpecialisedPromise的实例,属于未定义行为——标准明确要求协程句柄的模板类型必须与协程的Promise类型严格匹配。 - 生命周期问题:在Promise对象销毁后,再使用通过
from_promise或from_address构造的句柄,会导致访问已释放内存,触发未定义行为。 - 非法引用/地址:通过强制类型转换等非法手段获取Promise引用或地址,再传递给这两个方法,同样会导致未定义行为。
内容的提问来源于stack exchange,提问作者Alexandre S.
相关产品推荐
相关产品推荐

