为何无法将重载的std::sqrt传入std::function?C++技术问题
为什么直接传递
std::sqrt<Complex::value_type>会导致函数类型无法解析? 这个问题的核心原因是**std::sqrt存在多个重载版本**,当你直接传递模板特化后的std::sqrt<Complex::value_type>时,编译器无法确定你要引用的是哪一个重载,从而抛出类型解析错误。
具体细节拆解
当你包含了<valarray>头文件后,标准库会为std::sqrt新增一个针对std::valarray的重载:
template< class T > std::valarray<T> sqrt( const std::valarray<T>& );
这时候,即使你指定了模板参数Complex::value_type(也就是double),编译器面前会出现两个候选的std::sqrt重载:
- 处理复数的版本:
std::complex<double> std::sqrt(const std::complex<double>&) - 处理
valarray的版本:std::valarray<double> std::sqrt(const std::valarray<double>&)
而你的relay_complex_to_std函数期望接收的是std::function<Complex(const Complex&)>类型的参数,编译器没办法自动从这两个重载里选出匹配的那个,所以就报了"unresolved overloaded function type"的错误。
为什么lambda可以正常工作?
当你用lambda包裹std::sqrt时:
[](Complex a){return std::sqrt(a);}
lambda的参数类型明确是Complex(即std::complex<double>),编译器在lambda内部会直接匹配到std::sqrt的复数版本,完全没有歧义,自然就能正常编译。
其他可行的解决方案
除了用lambda包裹,你还可以通过强制类型转换明确指定要使用的重载版本:
return relay_complex_to_std(arg, static_cast<Complex(*)(const Complex&)>(std::sqrt));
这里把std::sqrt强制转换成指向复数版本的函数指针,直接消除了编译器的歧义问题。
验证代码(你提供的测试用例)
可以通过注释/取消注释<valarray>来复现问题:
#include <cmath> #include <complex> #include <functional> #include <iostream> //#include <valarray> // 取消注释后会触发重载歧义 using Complex = std::complex<double>; Complex relay(Complex arg, std::function<Complex(Complex)> f){ return f(arg); } int main(){ std::function<Complex(Complex)> f = std::sqrt<Complex::value_type>; std::cout << std::sqrt(4.0) << "\n"; std::cout << relay(Complex(-2,0), std::sqrt<Complex::value_type>) << "\n"; return 0; }
内容的提问来源于stack exchange,提问作者infinitezero
相关产品推荐
相关产品推荐

