Reputation: 1350
I'm looking for a function that returns a reference to real or imag values of a complex number in C++11. In C++03 I could say:
complex<double> C; cin >> C.real();
But in C++11 that gives me a compile error since the C.real() returns a value not a reference.
I found out that I can write this:
double t; cin >> t; C.real(t);
but it isn't straightforward and for example if I want to multiply the real part of c by 2 and ad it by 1 I should say:
C.real(2*C.real() + 1);
That is not clean.
Is there any other [clean] way to do that?
Upvotes: 4
Views: 4984
Reputation: 45424
Sorry to be negative, but your question starts from a wrong premise. Concerning std::complex
the 2011 standard is backward compatible. Code of the form
complex<double> C; cin >> C.real();
was never valid C++. The 2003 standard only gives the member function
T std::complext<T>::real() const;
but not
const T& std::complext<T>::real() const; // non-standard
T& std::complext<T>::real(); // non-standard
even though some implementations (such as that shipped with gcc 4.3) may have implemented these two instead.
Now, to answer your question. Clearly, the cleanest way is to follow the intention of the standard. The 2011 standard adds the following setters
void std::complex<T>::real(T);
void std::complex<T>::imag(T);
so you can now simply use those to set the real or imaginary parts separately.
However, those cannot be used in a function taking T&
, such as operator>>
. For that you must do some nasty tricks like
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);
Actually, as pointed out in a comment by bames53, the standard guarantees std::complex
to be laid out such that this always works.
Upvotes: 5
Reputation: 15814
C++11 now allows
double& re(std::complex<double>& c)
{
return reinterpret_cast<double (&)[2]>(c)[0];
}
double& im(std::complex<double>& c)
{
return reinterpret_cast<double (&)[2]>(c)[1];
}
const double& re(const std::complex<double>& c)
{
return reinterpret_cast<const double (&)[2]>(c)[0];
}
const double& im(const std::complex<double>& c)
{
return reinterpret_cast<const double (&)[2]>(c)[1];
}
Usage:
std::complex<double> a;
std::cin >> re(a);
Relevant quote §26.4:
Moreover, if a is an expression of type
cv std::complex<T>*
and the expressiona[i]
is well-defined for an integer expressioni
, then: —reinterpret_cast<cv T*>(a)[2*i]
shall designate the real part ofa[i]
, and —reinterpret_cast<cv T*>(a)[2*i+1]
shall designate the imaginary part ofa[i]
.
Upvotes: 4
Reputation: 41096
Not that I know of.
You could construct a helper if that's important to you:
class ModifyReal
{
double d;
complex<double> & c;
public:
ModifyReal(complex<double> & c_) : c(c_), d(numeric_limits<double>::quiet_NaN())
{}
operator double &() { return d; }
~ModifyReal() { c.real(d); }
};
cin >> ModifyReal(C);
I would not exactly recommend to use this, however, unless you have a very compelling reason to. ("I do not like it" is not convincing enough.)
I do think having many different classes like this in your code can hamper readability, but if you use it in a few dedicated instances you should be fine. Error handling can become subtley difficult (e.g. since cin doesn't throw on invalid input, C gets assigned nan, rather than being unmodified.)
What does "clean" mean? No, don't tell me - think about it.
Upvotes: 1
Reputation: 179799
Inspired by Steve Jessop, it's just C += (C + C.conj())/2 + 1;
.
Remember that in complex math, you cannot really treat the real and imaginary parts as fully independent components. That's just about as sane than treating their phase and magnitude as fully independent components. Addition of complex numbers is done independently on real and imaginary parts, but multiplication is done independently on the phase and magnitude parts.
Your example is not complex multiplication, so it makes sense that std::complex
doesn't support that kind of multiplication.
Upvotes: -2
Reputation: 55395
If you really want to separate input for real and imaginary parts of a complex, you could try IO manipulators approach.
#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);
}
You can put the above code in a header file of its own (if you do that, it might be a good idea to wrap it in a namespace).
Usage:
#include <iostream>
#include "my_header.h"
int main()
{
std::complex<double> c;
std::cin >> real >> c >> imag >> c;
if (std::cin) std::cout << c;
}
Hope I guessed your definition of "clean" correctly :)
Upvotes: 5
Reputation: 7996
If you want to manipulate real parts you can just use double or floats directly.
If you want to manipulate imaginary parts you can have a unique complex number std::complex<double> I(0,1)
and multiply it by the value you want.
For instance, instead of writing: C.real(2*C.real() + 1);
you can write: C += C.real() + 1;
Then you can mix doubles with complexs in your mathematical expressions and the compiler will use the correct conversions. See an example:
#include <iostream>
#include <complex>
int main(int argc, char* argv[])
{
// Let the user enter a Real number
double c;
std::cin >> c;
// Explicitly convert to a complex
std::complex<double> C = 2*c + 1;
std::cout << C << std::endl;
// Creates a pure imaginary complex number I
std::complex<double> I(0,1);
// Mix together complex and real numbers in the
// same expression
C = C + c*I;
std::cout << C << std::endl;
// Setup a specific value and compare how to achieve
// C.real = 2*C.real + 1
C = 1. + 2.*I;
C.real(2*C.real()+1);
std::complex<double> D = 1. + 2.*I;
D += D.real() + 1;
std::cout << "C=" << C << "\tD=" << D << std::endl;
return 0;
}
The output:
$ ./main.exe
1
(3,0)
(3,1)
C=(3,2) D=(3,2)
$ ./main.exe
2
(5,0)
(5,2)
C=(3,2) D=(3,2)
If you are afraid of the lost of efficiency of this method compared to affecting directly through a reference you can look at the generated assembly code. On my computer with g++
and -O3
everything is inlined.
Upvotes: 2