std::vector<std::complex<float> > c;
std::vector<float> d;
std::transform(c.begin(), c.end(), d.begin(), std::real<float>);
为什么编译器不能从重载函数中解析地址real<float>
?
编译器指的是哪些重载函数?
std::vector<std::complex<float> > c;
std::vector<float> d;
std::transform(c.begin(), c.end(), d.begin(), std::real<float>);
为什么编译器不能从重载函数中解析地址real<float>
?
编译器指的是哪些重载函数?
您的库实现为std::real<float>
.
26.4.9 附加重载 [cmplx.over]
1 以下函数模板应具有额外的重载:
arg norm conj proj imag real
- 2 附加过载应足以确保:
- 如果参数有类型
long double
,那么它被有效地强制转换为complex<long double>
。- 否则,如果参数具有类型
double
或整数类型,则有效地将其强制转换为complex<double>
.- 否则,如果参数的类型为
float
,则它被有效地强制转换为complex<float>
。[...]
您可以只使用基于...的范围
for (auto v : c) d.push_back(real(v));
...或将调用打包real
到仿函数或其他函数中...
struct my_caller {
template <typename T> T operator() (std::complex<T> const &c) {
return real(c);
}
};
...或使用成员函数...
std::transform(c.begin(), c.end(), d.begin(), [](std::complex<T> const &c) {
return c.real();
});
重要的:
请注意,使用时您必须在目标中有足够的空间transform
:
std::vector<float> d (c.size());
或使用后插入器:
std::transform(c.begin(), c.end(), back_inserter(d), ...);
否则,您将遍历未定义的内存,从而产生未定义的行为。
§26.4.9规定(除其他外),real
对于 float、double 和 long double 类型的参数,应具有额外的重载。看来你的图书馆实现为这些重载做了一个模板,也许像
template <typename T>
T real(T const& t)
{
return std::real(std::complex<T>{t});
}
除了 phresnel 提供的解决方案之外,您还可以明确告诉编译器您指的是哪种函数指针:
std::transform(c.begin(), c.end(), d.begin(), (float(*)(std::complex<float> const&))std::real<float>);
然后编译器寻找一个std::real
可以转换成给定类型的函数指针的指针,并找到正确的指针。
我告诉你这只是为了完整性 - 我认为这种显式转换很难看,并且更喜欢基于范围的 for 或使用 lambda 进行转换。