简体   繁体   English

如何用“std::function”替换“float (*fSqrt)(float)”<float(float) fSqrt> “在 C++ 中?

[英]How to replace "float (*fSqrt)(float)" with "std::function<float(float) fSqrt>" in C++?

I have a function with signature:我有一个带签名的函数:
template<class Type> bool isPrime(const Type& n,float (*fSqrt)(float),bool debug = false)
which works fine.这工作正常。

But,但,
template<class Type> bool isPrime(const Type& n,std::function<float(float)> fSqrt,bool debug = false)
causes compile-error.导致编译错误。

How to replace float (*fSqrt)(float) with std::function<float(float) fSqrt> ?如何用std::function<float(float) fSqrt>替换float (*fSqrt)(float)
Please note: My ultimate objective is std::function<float(Type)> , where Type is templated.请注意:我的最终目标是std::function<float(Type)> ,其中Type是模板化的。

Wandbox ( https://wandbox.org/ ) shows: Wandbox ( https://wandbox.org/ ) 显示:

prog.cc: In function 'int main()':
prog.cc:91:28: error: no matching function for call to 'isPrime(int&, <unresolved overloaded function type>, bool)'
   91 |         std::cout<<(isPrime(n,std::sqrt,true)?"Positive":"Negative")<<'\n';
      |                     ~~~~~~~^~~~~~~~~~~~~~~~~~
prog.cc:10:27: note: candidate: 'template<class Type> bool isPrime(const Type&, const float&, bool)'
   10 | template<class Type> bool isPrime(const Type& n,const float& nSqrt = 0.0,bool debug = false) {
      |                           ^~~~~~~
prog.cc:10:27: note:   template argument deduction/substitution failed:
prog.cc:91:28: note:   cannot convert 'std::sqrt' (type '<unresolved overloaded function type>') to type 'const float&'
   91 |         std::cout<<(isPrime(n,std::sqrt,true)?"Positive":"Negative")<<'\n';
      |                     ~~~~~~~^~~~~~~~~~~~~~~~~~
prog.cc:81:27: note: candidate: 'template<class Type> bool isPrime(const Type&, std::function<float(float)>, bool)'
   81 | template<class Type> bool isPrime(const Type& n,std::function<float(float)> fSqrt,bool debug = false) {    // Type & std::function - compile-error
      |                           ^~~~~~~
prog.cc:81:27: note:   template argument deduction/substitution failed:
prog.cc:91:28: note:   cannot convert 'std::sqrt' (type '<unresolved overloaded function type>') to type 'std::function<float(float)>'
   91 |         std::cout<<(isPrime(n,std::sqrt,true)?"Positive":"Negative")<<'\n';
      |                     ~~~~~~~^~~~~~~~~~~~~~~~~~

OnlineGDB ( https://www.onlinegdb.com/# ) shows: OnlineGDB ( https://www.onlinegdb.com/# ) 显示:

main.cpp:91:38: error: no matching function for call to ‘isPrime(int&, , bool)’
  std::cout<<(isPrime(n,std::sqrt,true)?"Positive":"Negative")<<'\n';
                                      ^
main.cpp:10:27: note: candidate: template bool isPrime(const Type&, const float&, bool)
 template<class Type> bool isPrime(const Type& n,const float& nSqrt = 0.0,bool debug = false) {
                           ^~~~~~~
main.cpp:10:27: note:   template argument deduction/substitution failed:
main.cpp:91:38: note:   cannot convert ‘sqrt’ (type ‘’) to type ‘const float&’
  std::cout<<(isPrime(n,std::sqrt,true)?"Positive":"Negative")<<'\n';
                                      ^
main.cpp:81:27: note: candidate: template bool isPrime(const Type&, std::function, bool)
 template<class Type> bool isPrime(const Type& n,std::function<float(float)> fSqrt,bool debug = false) {    // Type & std::function - compile-error
                           ^~~~~~~
main.cpp:81:27: note:   template argument deduction/substitution failed:
main.cpp:91:38: note:   cannot convert ‘sqrt’ (type ‘’) to type ‘std::function’
  std::cout<<(isPrime(n,std::sqrt,true)?"Positive":"Negative")<<'\n';
                                      ^

Kindly help me out, please.请帮助我,请。
Thank you :)谢谢 :)

As others have pointed out std::sqrt has multiple overload, and you should specify which one to deduce there to be a std:.function .正如其他人指出的那样std::sqrt有多个重载,您应该指定哪一个来推断存在std:.function For example static_cast<float(*)(float)>(std::sqrt) .例如static_cast<float(*)(float)>(std::sqrt)

However, you should not be taking the address of a standard library function.但是,您不应该获取标准库函数的地址。 See in detail here: Can I take the address of a function defined in standard library?在此处详细查看: 我可以获取标准库中定义的函数的地址吗?

Secondly the std::function comes with a type-erasure overhead .其次, std::function带有类型擦除开销

Therefore, I suggest packing the std::sqrt to a lambda, and use template argument to deduce the lambda by the compiler.因此,我建议将std::sqrt打包为 lambda,并使用模板参数由编译器推导出 lambda。 Something like就像是

template<class Type, typename Callable> 
bool isPrime(const Type& n, Callable fSqrt, bool debug = false)
{
    // ...
}

and call via并通过调用

isPrime(2.f, [](float val) { return std::sqrt(val); });

However, now isPrime takes anything callable.但是,现在isPrime接受任何可调用的。 This can be restricted only for the specific one by sfinaeing the function.这可以通过 sfinaeing 功能仅针对特定的功能进行限制。

#include <type_traits> // std::enable_if, std::is_floating, std::invoke_result

template<class Type, typename Callable> 
auto isPrime(const Type& n, Callable fSqrt, bool debug = false)
->std::enable_if_t<std::is_floating_point_v<std::invoke_result_t<Callable, Type>>, bool>
{
    // ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM