如何将 std::sqrt 用作 std::function?
How to use std::sqrt as std::function?
代码如下:
#include <iostream>
#include <cmath>
#include <functional>
#include <complex>
int main() {
// This works.
std::function<float(float)> f = [](auto const& x) {return std::sqrt(x);};
// This also works. Why this works?!
using Complex = std::complex<double>;
std::function<Complex(const Complex&)> g = std::sqrt<double>;
// All of the following doesn't work.
// error: conversion from ‘<unresolved overloaded function type>’
// to non-scalar type ‘std::function<float(float)>’ requested
std::function<float(float)> a = std::sqrtf<float>;
std::function<float(float)> b = std::sqrt<float>;
std::function<float(float)> c = std::sqrt;
std::function<double(double)> d = std::sqrt<double>;
}
考虑到 std::sqrt reference,我真的很困惑为什么涉及复杂的一个有效,而其他的为什么不起作用。
我知道 ,但是,我对使用 std::complex
不感兴趣,而且,这个问题的 OP 特别要求 std::complex
,相反,我只想使用 float
或 double
(或实值,不复杂)。
这是怎么回事?
这样做的正确方法是什么?
Considering the std::sqrt reference,
您看错了std::sqrt
页面:是非模板版本的页面。
如果您使用 std::sqrt<double>
和 std::sqrt<float>
函数,则您使用的是 std::sqtr
的 模板 版本,在 this page.
如您所见,std::sqrt<T>
template< class T >
complex<T> sqrt( const complex<T>& z );
收到一个std::complex<T>
和return一个std::complex<T>
。
所以当你写
std::function<float(float)> f = [](auto const& x) {return std::sqrt(x);};
之所以有效,是因为 lambda 调用(std::sqrt(x)
,其中 x
是一个 float
)非模板函数。
写的时候
std::function<Complex(const Complex&)> g = std::sqrt<double>;
之所以有效,是因为 std::sqrt<double>
是 std::sqrt
的模板版本,它收到 Complex const &
(std::complex<double> const &
)和 return Complex const &
但是当你把东西写成
std::function<float(float)> b = std::sqrt<float>;
std::function<double(double)> d = std::sqrt<double>;
您将函数接收和 return 复杂传递给 std::function
等待函数接收和 return 简单(非复杂)浮点类型。
为了让它工作,你必须使用 std::sqrt
的非模板版本(所以没有 <float>
也没有 <double>
)并转换正确的指针类型(到 select std::sqrt
非模板但重载版本的正确版本)。这也适用于 c
.
std::function<float(float)> b = (float(*)(float))std::sqrt;
std::function<float(float)> c = (float(*)(float))std::sqrt;
std::function<double(double)> d = (double(*)(double))std::sqrt;
针对a
的问题
std::function<float(float)> a = std::sqrtf<float>;
不一样;您必须删除模板部分 (<float>
),因为 std::sqrtf
不是模板函数。
所以应该可以工作(std::sqrtf
没有超载,所以不需要强制转换,因为没有歧义)
std::function<float(float)> a = std::sqrtf;
不幸的是,我发现这不适用于 clang++ 和 g++。据我所知,这是因为 cmath
没有将 sqrtf
放入 std
命名空间(在我看来 g++ 和 clang++ 不符合要求)。
所以(使用 g++ 和 clang++)有效
std::function<float(float)> a = sqrtf;
std::sqrt()
和std::sqrtf()
的浮点重载不是模板,所以这些形式是无效语法:
std::function<float(float)> a = std::sqrtf<float>;
// and
std::function<double(double)> d = std::sqrt<double>;
这个表格:
std::function<float(float)> c = std::sqrt;
没问题,只是 std::sqrt()
超载了,所以名称不能像未超载时那样退化为单个指针。
为了消除使用哪个重载的歧义,您需要将函数转换为正确的类型:
std::function<float(float)> works = static_cast<float(*)(float)>(std::sqrt);
但是如您所见,语法有点冗长,这就是为什么 lambda 版本是执行此操作的首选方法。
此表单有效的原因:
std::function<Complex(const Complex&)> g = std::sqrt<double>;
是因为std::complex
版本的std::sqrt()
是模板,其中模板参数是复杂对象的底层类型。
代码如下:
#include <iostream>
#include <cmath>
#include <functional>
#include <complex>
int main() {
// This works.
std::function<float(float)> f = [](auto const& x) {return std::sqrt(x);};
// This also works. Why this works?!
using Complex = std::complex<double>;
std::function<Complex(const Complex&)> g = std::sqrt<double>;
// All of the following doesn't work.
// error: conversion from ‘<unresolved overloaded function type>’
// to non-scalar type ‘std::function<float(float)>’ requested
std::function<float(float)> a = std::sqrtf<float>;
std::function<float(float)> b = std::sqrt<float>;
std::function<float(float)> c = std::sqrt;
std::function<double(double)> d = std::sqrt<double>;
}
考虑到 std::sqrt reference,我真的很困惑为什么涉及复杂的一个有效,而其他的为什么不起作用。
我知道 std::complex
不感兴趣,而且,这个问题的 OP 特别要求 std::complex
,相反,我只想使用 float
或 double
(或实值,不复杂)。
这是怎么回事? 这样做的正确方法是什么?
Considering the std::sqrt reference,
您看错了std::sqrt
页面:是非模板版本的页面。
如果您使用 std::sqrt<double>
和 std::sqrt<float>
函数,则您使用的是 std::sqtr
的 模板 版本,在 this page.
如您所见,std::sqrt<T>
template< class T >
complex<T> sqrt( const complex<T>& z );
收到一个std::complex<T>
和return一个std::complex<T>
。
所以当你写
std::function<float(float)> f = [](auto const& x) {return std::sqrt(x);};
之所以有效,是因为 lambda 调用(std::sqrt(x)
,其中 x
是一个 float
)非模板函数。
写的时候
std::function<Complex(const Complex&)> g = std::sqrt<double>;
之所以有效,是因为 std::sqrt<double>
是 std::sqrt
的模板版本,它收到 Complex const &
(std::complex<double> const &
)和 return Complex const &
但是当你把东西写成
std::function<float(float)> b = std::sqrt<float>;
std::function<double(double)> d = std::sqrt<double>;
您将函数接收和 return 复杂传递给 std::function
等待函数接收和 return 简单(非复杂)浮点类型。
为了让它工作,你必须使用 std::sqrt
的非模板版本(所以没有 <float>
也没有 <double>
)并转换正确的指针类型(到 select std::sqrt
非模板但重载版本的正确版本)。这也适用于 c
.
std::function<float(float)> b = (float(*)(float))std::sqrt;
std::function<float(float)> c = (float(*)(float))std::sqrt;
std::function<double(double)> d = (double(*)(double))std::sqrt;
针对a
的问题
std::function<float(float)> a = std::sqrtf<float>;
不一样;您必须删除模板部分 (<float>
),因为 std::sqrtf
不是模板函数。
所以应该可以工作(std::sqrtf
没有超载,所以不需要强制转换,因为没有歧义)
std::function<float(float)> a = std::sqrtf;
不幸的是,我发现这不适用于 clang++ 和 g++。据我所知,这是因为 cmath
没有将 sqrtf
放入 std
命名空间(在我看来 g++ 和 clang++ 不符合要求)。
所以(使用 g++ 和 clang++)有效
std::function<float(float)> a = sqrtf;
std::sqrt()
和std::sqrtf()
的浮点重载不是模板,所以这些形式是无效语法:
std::function<float(float)> a = std::sqrtf<float>;
// and
std::function<double(double)> d = std::sqrt<double>;
这个表格:
std::function<float(float)> c = std::sqrt;
没问题,只是 std::sqrt()
超载了,所以名称不能像未超载时那样退化为单个指针。
为了消除使用哪个重载的歧义,您需要将函数转换为正确的类型:
std::function<float(float)> works = static_cast<float(*)(float)>(std::sqrt);
但是如您所见,语法有点冗长,这就是为什么 lambda 版本是执行此操作的首选方法。
此表单有效的原因:
std::function<Complex(const Complex&)> g = std::sqrt<double>;
是因为std::complex
版本的std::sqrt()
是模板,其中模板参数是复杂对象的底层类型。