std::real() is broken when using -std=c++0x mode
Mark Tall
mtall.gcc@gmail.com
Wed Nov 16 12:35:00 GMT 2011
With -std=c++0x mode, std::real() from <complex> appears to be broken.
More specifically, with -std=c++0x enabled, std::real() is confused
with a user version of real(), which is in a separate namespace.
The output of the program listed below should be:
A.val = (123,456)
B.val = 123
When using -std=c++0x, the following error occurs during compilation:
real_bug.cpp: In function ‘int main(int, char**)’:
real_bug.cpp:93: error: no match for ‘operator=’ in ‘B = std::real
[with _Tp = mylib::Mat<std::complex<double> >](A)’
real_bug.cpp:52: note: candidates are: mylib::Mat<double>&
mylib::Mat<double>::operator=(const mylib::Mat<double>&)
Note that the compiler wants to call std::real(), while it should be
calling mylib::real() instead.
I'm using gcc 4.4.5 from Scientific Linux 6.1 (a clone of Red Hat
Enterprise Linux 6.1) on an x86_64 machine. I've also tried clang++
2.8, and the code compiles fine.
A colleague has also encountered a similar bug (or perhaps the same
bug) in gcc 4.6.
Bug filed as:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51158
real_bug.cpp:
#include <iostream>
#include <complex>
namespace mylib
{
template<typename T, typename derived>
struct Base
{
const derived& get_ref() const
{ return static_cast<const derived&>(*this); }
};
template<typename T, typename Obj>
class delayed_real;
template<typename T>
class Mat;
template<typename T>
struct strip_cx
{ typedef T result; };
template<typename T>
struct strip_cx< std::complex<T> >
{ typedef T result; };
template<typename T>
const T&
get_real(const T& X) { return X; }
template<typename T>
const T
get_real(const std::complex<T>& X) { return X.real(); }
template<typename out_T, typename Obj>
struct
delayed_real
{
const Obj& X;
explicit delayed_real(const Obj& in_X) : X(in_X) {}
};
template<typename T>
struct
Mat : public Base< T, Mat<T> >
{
T val;
Mat() : val() {}
template<typename Obj>
void
operator=(const delayed_real<T, Obj>& tmp)
{ val = get_real(tmp.X.val); }
};
template<typename T, typename Obj>
const delayed_real< typename strip_cx<T>::result, Obj>
real(const Base< std::complex<T>, Obj>& X)
{
return
delayed_real< typename strip_cx<T>::result, Obj >
(X.get_ref());
}
}
using namespace std;
using namespace mylib;
int
main(int argc, char** argv)
{
typedef std::complex<double> cx_double;
Mat<cx_double> A;
A.val = cx_double(123,456);
cout << "A.val = " << A.val << endl;
Mat<double> B;
B = real(A); // broken when using -std=c++0x
// explicit namespace specification required for -std=c++0x
//B = mylib::real(A);
cout << "B.val = " << B.val << endl;
return 0;
}
More information about the Libstdc++
mailing list