从重载函数std :: real <float> </float>解析地址

时间:2013-04-03 06:07:24

标签: c++ algorithm stl overloading

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

为什么编译器无法解析重载函数real<float>中的地址?

编译器意味着哪些重载函数?

2 个答案:

答案 0 :(得分:5)

您的库实现为std::real<float>提供了额外的重载。

为什么重载?

  

26.4.9附加重载[cmplx.over]

     
      
  • 1以下功能模板应具有额外的重载:

    arg norm
    conj proj
    imag real
    
  •   
  • 2额外的重载应足以确保:   
        
    1. 如果参数的类型为long double,则会将其有效地转换为complex<long double>
    2.   
    3. 否则,如果参数的类型为double或整数类型,则它会被有效地转换为complex<double>
    4.   
    5. 否则,如果参数的类型为float,则它有效地转换为complex<float>
    6.   
  •   
     

[...]

解决问题的方法:

您可以使用基于...的范围

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), ...);

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

答案 1 :(得分:4)

§26.4.9声明(其中)real对于float,double和long double类型的参数应该有额外的重载。看来你的libraray实现为这些重载做了一个模板,可能就像

template <typename T>
T real(T const& t)
{
  return std::real(std::complex<T>{t});
}

除了phresnel priovided解决方案之外,你可以明确告诉编译器你指的是哪种函数指针:

std::transform(c.begin(), c.end(), d.begin(), (float(*)(std::complex<float> const&))std::real<float>);

然后,编译器会查找可以转换为给定类型的函数指针的std::real,并找到正确的函数指针。

我告诉你这只是为了完整 - 我认为这个显式转换丑陋,并且更喜欢基于范围或用lambda转换。