7
std::vector<std::complex<float> > c;
std::vector<float> d;
std::transform(c.begin(), c.end(), d.begin(), std::real<float>);

为什么编译器不能从重载函数中解析地址real<float>

编译器指的是哪些重载函数?

4

2 回答 2

5

您的库实现为std::real<float>.

为什么会超载?

26.4.9 附加重载 [cmplx.over]

  • 1 以下函数模板应具有额外的重载:

    arg norm
    conj proj
    imag real
    
  • 2 附加过载应足以确保:
    1. 如果参数有类型long double,那么它被有效地强制转换为complex<long double>
    2. 否则,如果参数具有类型double或整数类型,则有效地将其强制转换为complex<double>.
    3. 否则,如果参数的类型为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), ...);

否则,您将遍历未定义的内存,从而产生未定义的行为。

于 2013-04-03T06:40:05.887 回答
4

§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 进行转换。

于 2013-04-03T06:55:07.673 回答