c++ 使用std::transform和tr1::bind转换std::complex的向量

x0fgdtte  于 2024-01-09  发布在  其他
关注(0)|答案(3)|浏览(121)

给定一个std::complex的std::vector,我想把它转换成一个只包含复数的真实的部分的向量,除以某个常数系数。现在,我这样做:

  1. std::vector<std::complex<double> > vec;
  2. std::vector<double> realVec;
  3. double norm = 2.0;
  4. ...
  5. for (std::vector<std::complex<double> >::iterator it = vec.begin(), itEnd = vec.end(); it != itEnd; ++it)
  6. realVec.push_back((*it).real() / norm);

字符串
这当然很好用,但我正在寻找一种使用std::transform来做同样事情的方法。我试过:

  1. transform(vec.begin(), vec.end(), back_inserter(realVec), tr1::bind(divides<double>(), tr1::bind(&complex<double>::real, tr1::placeholders::_1), norm));


但它不会工作。我有这个错误:

  1. erreur: no matching function for call to bind(<unresolved overloaded function type>, std::tr1::_Placeholder<1>&)’|


我不明白为什么有一个“未解析的重载函数类型”。
有人能给我解释一下怎么了吗?

vxf3dgd4

vxf3dgd41#

不幸的是,你不能这样做,至少不能直接这样做。标准库成员函数的类型(如complex<double>::real)是未指定的,所以一个实现可能会提供额外的重载,并且那里的函数可能会有额外的带默认参数的参数。
实际上,没有可移植的方法来获取标准库成员函数的地址。
最好的办法是写一个helper函数:

  1. template <typename T>
  2. T get_real(const std::complex<T>& c) { return c.real(); }

字符串
并绑定到:

  1. std::tr1::bind(&get_real<double>, std::tr1::placeholders::_1)

xcitsw88

xcitsw882#

std::complex<>::real()是重载的(参见C++11 [complex])。

  1. template <typename T>
  2. class complex {
  3. // ...
  4. T real() const; // getter
  5. void real( T ); // setter
  6. // ...
  7. };

字符串
C++在获取重载函数的地址时需要消除歧义。在你的例子中,你必须说:

  1. tr1::bind( static_cast<double(std::complex<double>::*)()const>( &std::complex<double>::real ),
  2. tr1::placeholders::_1 )


是的,这是丑陋的。

展开查看全部
kyxcudwk

kyxcudwk3#

对于C++11,您可以编写

  1. #include <algorithm>
  2. #include <complex>
  3. #include <functional>
  4. #include <iostream>
  5. #include <vector>
  6. int main() {
  7. const std::vector<std::complex<double>> vec = {std::complex<double>(1, 0), std::complex<double>(0, 1)};
  8. std::vector<double> real_vec;
  9. constexpr double norm = 2.0;
  10. std::transform(vec.cbegin(), vec.cend(), std::back_inserter(real_vec), std::bind(std::divides<double>(), std::bind<double (*)(const std::complex<double> &)>(std::real, std::placeholders::_1), norm));
  11. for (const auto &elem : real_vec)
  12. std::cout << elem << '\n';
  13. }

字符串
你可以用using F = double (*)(const std::complex<double> &)来简化,写成std::bind<F>(std::real, std::placeholders::_1)。从C++14开始,标准运算符模板的模板类型参数一般可以省略,所以你可以写成std::divides<>()

展开查看全部

相关问题