You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何C++17中两段相似代码调用函数,一个抛出std::bad_any_cast异常?

问题原因分析

核心原因是函数调用时传递的参数值类别(左值/右值)不同,导致std::function的模板参数推导结果存在差异,最终与std::any中存储的类型匹配情况不同:

1. 先明确存储的基础类型

你存在std::any中的是std::function<std::any(Context*)>,这个函数对象接受的是值传递的Context*参数——对于标量类型(指针属于标量)来说,值传递的参数可以接受左值或右值的指针。

2. compute函数内调用失败的原因

在compute函数中,你传递给method_map的是左值Context*(比如一个命名变量的指针)。此时代码尝试通过std::any_cast获取std::function<std::any(Context*&)>类型的对象:

  • 这个目标类型要求参数是左值引用类型的Context*,和std::any中存储的std::function<std::any(Context*)>是完全不同的特化类型。
  • std::any的any_cast要求目标类型与存储类型严格匹配(或属于可隐式兼容的窄范围类型),这种不同引用修饰的std::function特化不属于兼容范畴,因此触发std::bad_any_cast异常。

3. main函数直接调用成功的原因

在main函数中,你传递的是右值Context*(比如临时创建的指针、或经std::move转换后的指针)。此时代码尝试std::any_cast到std::function<std::any(Context*&&)>:

  • std::function存在隐式适配规则:当存储的函数参数是值类型T时,它可以被隐式转换为接受T&&(右值引用)的std::function特化类型——因为右值可以被拷贝到值参数中,符合函数调用的语义。
  • 这种隐式转换被std::any_cast认可,因此转换成功,函数可以正常执行。

关键知识点补充

  • std::any存储的是具体的、无歧义的类型实例,any_cast不会自动进行复杂的类型转换,仅支持严格匹配或有限的隐式兼容转换。
  • std::function的不同参数引用修饰(T/T&/T&&)会生成完全不同的特化类型,其中只有T和T&&的特化存在隐式兼容可能,T和T&的特化则完全不兼容。

内容的提问来源于stack exchange,提问作者scengka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 11:56:08