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

发布于 2024-11-02 04:10:05 字数 859 浏览 5 评论 0原文

给定 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>&)’|

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

有人可以向我解释一下出了什么问题吗?

Given a std::vector of std::complex, I would like to transform it to a vector containing only the real part of the complex, divided by some constant coefficient.
Right now, I do that:

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

This works fine of course, but I am looking for a way to use std::transform to do the same thing. I tried:

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

But it won't work. I have this error:

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

I don't understand why there is a "unresolved overloaded function type".

Could someone explain to me what is wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

开始看清了 2024-11-09 04:10:05

不幸的是,你不能这样做,至少不能直接这样做。标准库成员函数的类型(如complex::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)

Unfortunately, you can't do this, at least not directly. The types of Standard Library member functions (like complex<double>::real) are left unspecified, so an implementation may provide additional overloads and the functions that are there may have additional parameters with default arguments.

In effect, there is no portable way to take the address of a Standard Library member function.

Your best bet would be to write a helper function:

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

and bind to that:

std::tr1::bind(&get_real<double>, std::tr1::placeholders::_1)
筑梦 2024-11-09 04:10:05

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

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 )

是的,这很丑陋。

std::complex<>::real() is overloaded (cf. C++11 [complex]).

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

C++ requires a disambiguation when you take the address of an overloaded function. In your case, you have to say:

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

Yes, this is ugly.

春夜浅 2024-11-09 04:10:05

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

#include <algorithm>
#include <complex>
#include <functional>
#include <iostream>
#include <vector>

int main() {
    const std::vector<std::complex<double>> vec = {std::complex<double>(1, 0), std::complex<double>(0, 1)};
    std::vector<double> real_vec;
    constexpr double norm = 2.0;
    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));
    for (const auto &elem : real_vec)
        std::cout << elem << '\n';
}

You can simple by using F = double (*)(const std::complex&) 并编写 std::bind;(std::real,std::占位符::_1)。从 C++14 开始,标准运算符模板的模板类型参数通常可以省略,因此您可以编写 std::divides<>()

For C++11, you can write

#include <algorithm>
#include <complex>
#include <functional>
#include <iostream>
#include <vector>

int main() {
    const std::vector<std::complex<double>> vec = {std::complex<double>(1, 0), std::complex<double>(0, 1)};
    std::vector<double> real_vec;
    constexpr double norm = 2.0;
    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));
    for (const auto &elem : real_vec)
        std::cout << elem << '\n';
}

You can simplify by using F = double (*)(const std::complex<double> &) and write std::bind<F>(std::real, std::placeholders::_1). Since C++14, the template type argument for the standard operator templates can generally be omitted, so you can write std::divides<>().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文