【问题标题】:How to replace "float (*fSqrt)(float)" with "std::function<float(float) fSqrt>"?如何用“std::function<float(float) fSqrt>”替换“float (*fSqrt)(float)”?
【发布时间】:2021-12-07 21:20:07
【问题描述】:

我有一个带有签名的函数:

template<class Type> 
bool isPrime(const Type& n,float (*fSqrt)(float),bool debug = false)

效果很好。但是,

template<class Type> 
bool isPrime(const Type& n,std::function<float(float)> fSqrt,bool debug = false)

导致编译错误。

如何将float (*fSqrt)(float) 替换为std::function&lt;float(float)&gt; fSqrt
请注意:我的最终目标是 std::function&lt;float(Type)&gt;,其中 Type 是模板化的。

魔杖盒 (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/#) 显示:

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';
                                      ^

【问题讨论】:

  • sqrt 已超载,您必须将其转换为 static_cast&lt;float(*)(float)&gt;(std::sqrt) 才能选择正确的。
  • 只需将std::sqrt 更改为::sqrt

标签: c++ function c++11 templates std-function


【解决方案1】:

正如其他人指出的那样,std::sqrt 有多个重载,您应该指定要推断出哪一个是std:.function。例如static_cast&lt;float(*)(float)&gt;(std::sqrt)

但是,您不应该获取标准库函数的地址。 在这里详细查看: Can I take the address of a function defined in standard library?

其次是std::function comes with a type-erasure overhead

因此,我建议将std::sqrt 打包成一个 lambda,并使用模板参数由编译器推导出 lambda。类似的东西

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

并通过调用

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

然而,现在isPrime 接受任何可调用的东西。这可以通过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>
{
    // ...
}

【讨论】:

  • 谢谢@JeJo。 [1.] 已经有static_assert (std::is_integral&lt;Type&gt;::value,"ERR: integral type required");。 [2.] 为什么编译器不能推断出这个static_cast&lt;float(*)(float)&gt;(std::sqrt)
猜你喜欢
  • 2023-03-23
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-28
相关资源
最近更新 更多