【问题标题】:Using std::transform and tr1::bind to transform a vector of std::complex使用 std::transform 和 tr1::bind 转换 std::complex 的向量
【发布时间】:2011-08-08 17:29:31
【问题描述】:

给定 std::complex 的 std::vector,我想将其转换为仅包含复数实部的向量,除以某个常数系数。 现在,我就是这样做的:

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

这当然可以,但我正在寻找一种方法来使用 std::transform 来做同样的事情。我试过了:

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

但这行不通。我有这个错误:

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

我不明白为什么会有“未解析的重载函数类型”。

谁能给我解释一下怎么回事?

【问题讨论】:

  • 我知道这可能是异端,但 IMO 使用 for 循环的版本要清晰得多。

标签: c++ bind transform complex-numbers


【解决方案1】:

std::complex&lt;&gt;::real() 已重载(参见 C++11 [复杂])。

template <typename T>
class complex {
    // ...
    T real() const; // getter
    void real( T ); // setter
    // ...
};

当您获取重载函数的地址时,C++ 需要消除歧义。在你的情况下,你必须说:

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

是的,这很丑。

【讨论】:

  • 不幸的是,这并不容易,因为允许实现提供额外的重载或向现有重载添加带有默认参数的额外参数。 :(
  • @James:当然,但是 OP 询问 为什么 他得到了那个错误。 Legalese 很好,但是说“你不能在命名空间 std 中命名类的成员函数的类型”错过了 OP 的问题 IMO,这是在获取重载函数的地址时需要消除歧义。
【解决方案2】:

很遗憾,您不能这样做,至少不能直接这样做。标准库成员函数的类型(如complex&lt;double&gt;::real)未指定,因此实现可能会提供额外的重载,并且其中的函数可能具有带有默认参数的额外参数。

实际上,没有可移植的方式来获取标准库成员函数的地址。

最好的办法是编写一个辅助函数:

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

并绑定到那个:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    • 2013-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多