为何std::optional::transform直接调用std::addressof编译失败?
问题原因分析
核心问题:重载集合导致的函数指针歧义
直接使用std::addressof<int>时,编译器无法确定要引用哪个重载的函数,进而导致std::optional::transform的模板参数推导失败。
std::addressof的重载设计
标准库中std::addressof包含两个模板重载:
// 正常可用的重载:接受左值引用 template<class T> constexpr T* addressof(T& arg) noexcept; // 被删除的重载:禁止接受右值引用 template<class T> const T* addressof(const T&&) = delete;
当你显式指定模板参数std::addressof<int>时,编译器会实例化出两个具体函数:
int* addressof(int&)(可用)const int* addressof(const int&&)(已删除)
此时std::addressof<int>是一个重载函数集合,编译器无法自动确定你要传递哪个函数的地址给transform,这直接触发了模板参数推导失败。
自定义包装函数的差异
你写的arg_to_pointer<int>只有唯一的重载:
constexpr int* arg_to_pointer(int& arg) noexcept { return std::addressof(arg); }
不存在重载歧义,编译器可以明确获取它的函数指针,因此能顺利通过transform的模板参数推导。
验证与解决方法
如果要直接使用std::addressof,可以通过强制类型转换明确指定要引用的重载:
auto * test = foo.transform( static_cast<int*(*)(int&)>(std::addressof<int>) ).value_or(nullptr);
这样编译器就能确定要使用的是接受左值引用的那个重载,代码即可正常编译。
内容的提问来源于stack exchange,提问作者R K
相关产品推荐
相关产品推荐

