在C++ 11中返回对复数的实数或图像值的引用的函数

Far*_*zam 4 c++ gcc complex-numbers c++11

我正在寻找一个函数,它返回对C++ 11中复数的实数或图像值的引用.在C++ 03中,我可以说:

complex<double> C; cin >> C.real();

但是在C++ 11中,由于C.real()返回的值不是引用,因此给出了编译错误.

我发现我可以这样写:

double t; cin >> t; C.real(t);

但它并不简单,例如,如果我想将c的实部乘以2并将其加1,我应该说:

C.real(2*C.real() + 1);

那不干净.

还有其他[干净]的方法吗?

jro*_*rok 5

如果您真的想要为复杂的实部和虚部分开输入,可以尝试IO操纵器方法.

#include <complex>
#include <iosfwd>

class proxy_complex {
    explicit proxy_complex(std::istream& strm, bool f)
        : strm_(&strm), flag(f) { }
    proxy_complex(const proxy_complex&) = default;

    std::istream* strm_;
    bool flag;           // flag to check whether we're writing real or imag

public:
    template<typename T>
    std::istream& operator>>(std::complex<T>& c)
    {
        T n;
        if (*strm_ >> n)
            flag ? c.real(n) : c.imag(n);
        return *strm_;
    }

    friend proxy_complex operator>>(std::istream& is, proxy_complex(*func)(std::istream&))
    {
        return func(is);
    }
    friend proxy_complex real(std::istream&);
    friend proxy_complex imag(std::istream&);
};

inline proxy_complex real(std::istream& is)
{
    return proxy_complex(is, true);
}

inline proxy_complex imag(std::istream& is)
{
    return proxy_complex(is, false);
}
Run Code Online (Sandbox Code Playgroud)

您可以将上面的代码放在自己的头文件中(如果这样做,将它包装在命名空间中可能是个好主意).

用法:

#include <iostream>
#include "my_header.h"

int main()
{
    std::complex<double> c;
    std::cin >> real >> c >> imag >> c;
    if (std::cin) std::cout << c;
}
Run Code Online (Sandbox Code Playgroud)

希望我猜对你正确定义"干净":)


Wal*_*ter 5

很抱歉持否定态度,但你的问题是从错误的前提开始的。关于std::complex2011标准是向后兼容的。表格代码

complex<double> C; cin >> C.real();
Run Code Online (Sandbox Code Playgroud)

从来都不是有效的 C++。2003年标准只给出了成员函数

T std::complext<T>::real() const;
Run Code Online (Sandbox Code Playgroud)

但不是

const T& std::complext<T>::real() const;  // non-standard
T& std::complext<T>::real();              // non-standard
Run Code Online (Sandbox Code Playgroud)

即使某些实现(例如 gcc 4.3 附带的实现)可能已经实现了这两个。

现在,回答你的问题。显然,最干净的方法是遵循标准的意图。2011年标准添加了以下设置器

void std::complex<T>::real(T);
void std::complex<T>::imag(T);
Run Code Online (Sandbox Code Playgroud)

所以你现在可以简单地使用它们来分别设置实部或虚部。

但是,这些不能用在采用 的函数中T&,例如operator>>。为此,你必须做一些令人讨厌的把戏,比如

template<typename T>
inline T& get_real(std::complex<T>&z) { return reinterpret_cast<T(&)[2]>(z)[0]; }

template<typename T>
inline T& get_imag(std::complex<T>&z) { return reinterpret_cast<T(&)[2]>(z)[1]; }

std::complex<double> z;
cin >> get_real(z) >> get_imag(z);
Run Code Online (Sandbox Code Playgroud)

实际上,正如 bames53 的评论中指出的那样,该标准保证std::complex了其始终有效。