Why is std::complex real member function not const? - c++

Any reason for the member functions "real" and "imag" in the std::complex class not to be const?

There are two overloads for real in the complex class template:
T real() const;
void real(T);
The first on is const, so that can't be what you're asking about.
The second one, which takes a T argument and returns nothing, is not const, because it's a "setter" method—the whole point of it is to change the state of the object, so it had better not be const.

Let's look at the C++ Standard:
C++ 2011 Section 26.4.2 Class Template Complex
namespace std {
template<class T>
class complex {
public:
typedef T value_type;
complex(const T& re = T(), const T& im = T());
complex(const complex&);
template<class X> complex(const complex<X>&);
T real() const;
void real(T);
T imag() const;
void imag(T);
complex<T>& operator= (const T&);
complex<T>& operator+=(const T&);
complex<T>& operator-=(const T&);
complex<T>& operator*=(const T&);
complex<T>& operator/=(const T&);
complex& operator=(const complex&);
template<class X> complex<T>& operator= (const complex<X>&);
template<class X> complex<T>& operator+=(const complex<X>&);
template<class X> complex<T>& operator-=(const complex<X>&);
template<class X> complex<T>& operator*=(const complex<X>&);
template<class X> complex<T>& operator/=(const complex<X>&);
};
}
I'd say that it's pretty clearly stated that std::complex::real() and std::complex::imag() are const methods.

Related

template class 's non-member template operator overload syntax [duplicate]

I have a linking problem when using a home-made Complex class.
Class definition:
template<class T>
class Complex
{
public:
Complex(const T real = 0, const T imag = 0);
Complex(const Complex<T>& other);
~Complex(void) {};
Complex<T> operator*(const Complex<T>& other) const;
Complex<T> operator/(const Complex<T>& other) const;
Complex<T> operator+(const Complex<T>& other) const;
Complex<T> operator-(const Complex<T>& other) const;
friend void operator*=(const Complex<T>& z,const Complex<T>& other);
friend void operator/=(const Complex<T>& z,const Complex<T>& other);
friend void operator+=(const Complex<T>& z,const Complex<T>& other);
friend void operator-=(const Complex<T>& z,const Complex<T>& other);
void operator=(const Complex<T>& other);
friend T& real(Complex<T>& z);
friend T& imag(Complex<T>& z);
friend T abs(Complex<T>& z);
friend T norm(Complex<T>& z);
private:
T real_;
T imag_;
};
Implementation of abs:
template<class T>
T abs(Complex<T>& z)
{
return sqrt(z.real_*z.real_ + z.imag_*z.imag_);
}
I use the function abs like this : if(abs(z) <= 2).
Here are some errors I get:
Error 4 error LNK2001: unresolved external symbol "long double __cdecl abs(class Complex<long double> &)" (?abs##YAOAAV?$Complex#O###Z) C:\Users\Lucas\Documents\Visual Studio 2012\Projects\Fractals\Fractals\Main.obj Fractals
Error 3 error LNK2001: unresolved external symbol "long double & __cdecl imag(class Complex<long double> &)" (?imag##YAAAOAAV?$Complex#O###Z) C:\Users\Lucas\Documents\Visual Studio 2012\Projects\Fractals\Fractals\Main.obj Fractals
I get the same errors when using Complex<float> instead of Complex<long double>. I work with Visual C++ 2012. I would be really glad if you give me some hint on how to fix this. Thank you.
The function declared as
template <typename T>
class Complex {
// ...
friend T abs(Complex<T>& z);
// ...
};
is not a function template! It looks a bit like one as it is nested within a class template but that isn't quite enough. Here is what you probably meant to write:
template <typename T> class Complex;
template <typename T> T abs(Complex<T>&);
template <typename T>
class Complex {
// ...
friend T abs<T>(Complex<T>& z);
// ...
};
Alternatively, you could implement abs() when declaring it as friend.

questions about the implementation of Complex in c++'s library?

I find Complex's operator+ in MSVC return non-const Complex
_TMPLT(_Ty) inline
_CMPLX(_Ty) operator+(const _Ty& _Left,
const _CMPLX(_Ty)& _Right)
{ // add complex to real
_CMPLX(_Ty) _Tmp(_Left);
return (_Tmp += _Right);
}
Also, in cppreference, it is also non-const
template< class T >
complex<T> operator+( const complex<T>& lhs, const complex<T>& rhs);
(1)
template< class T >
complex<T> operator+( const complex<T>& lhs, const T& rhs);
(2)
template< class T >
complex<T> operator+( const T& lhs, const complex<T>& rhs);
(3)
template< class T >
complex<T> operator-( const complex<T>& lhs, const complex<T>& rhs);
(4)
template< class T >
complex<T> operator-( const complex<T>& lhs, const T& rhs);
(5)
template< class T >
complex<T> operator-( const T& lhs, const complex<T>& rhs);
(6)
template< class T >
complex<T> operator*( const complex<T>& lhs, const complex<T>& rhs);
(7)
template< class T >
complex<T> operator*( const complex<T>& lhs, const T& rhs);
(8)
template< class T >
complex<T> operator*( const T& lhs, const complex<T>& rhs);
(9)
template< class T >
complex<T> operator/( const complex<T>& lhs, const complex<T>& rhs);
(10)
template< class T >
complex<T> operator/( const complex<T>& lhs, const T& rhs);
(11)
template< class T >
complex<T> operator/( const T& lhs, const complex<T>& rhs);
Then someone maintains that it should be const.
However, I just can't think of such a situation which leads to the necessity of non-const.
Can someone show me such a situation? Thanks
You misunderstood the question and the answer you linked.
The answer doesn't say anything about the return value of a function. the answer talks about parameters passed to a function, and correctly suggests that parameters should be passed as constant references and constant pointers if that function doesn't mutate these parameters
Parameters should be passed as const references if that function doesn't mutate them
function should be declared as const if that function does not mutate the object it was called from.
there's is no reason for an operator + (const T& a , const T& b) to return const object, doing so may prevent important optimizations.

C++ template functions

This Vec template supports several functions such as multiplying a vector by scalar and adding vector to another vector.
The thing that is confusing me is that why the overloading of the second operator* is outside of the class template?
The operator* which is declared in the class overloads vectorXscalar
The one declared outside supports scalarXvector
template <class T>
class Vec {
public:
typename list<T>::const_iterator begin() const {
return vals_.begin();
}
typename list<T>::const_iterator end() const {
return vals_.end();
}
Vec() {};
Vec(const T& el);
void push_back(T el);
unsigned int size() const;
Vec operator+(const Vec& rhs) const;
Vec operator*(const T& rhs) const; //here
T& operator[](unsigned int ind);
const T& operator[](unsigned int ind) const;
Vec operator,(const Vec& rhs) const;
Vec operator[](const Vec<unsigned int>& ind) const;
template <class Compare>
void sort(Compare comp) {
vals_.sort(comp);
}
protected:
list<T> vals_;
};
template <class T>
Vec<T> operator*(const T& lhs, const Vec<T>& rhs); //and here!
template <class T>
ostream& operator<<(ostream& ro, const Vec<T>& v);
The operator* declared inside the template class could equally be written outside the class as
template <class T>
Vec<T> operator*(const Vec<T>& lhs, const T& rhs);
It can be written inside the class with a single argument (representing the rhs) because there is the implied *this argument used as the lhs of the operator.
The difference with the operator* defined outside the class is that the lhs of the operator is a template type. This allows the arguments to be supplied either way around when using the operator.
You are allowed to define the operator outside of a class with any arbitrary lhs and rhs types, but within the class are restricted to only varying the rhs. The compiler would select the best match of any defined operator* given the argument types.

Exporting templated inline functions - definition of function dllimport not allowed

I'm trying to implement math library but I'm stuck on exporting. I have a template class for 2-dimensional vector:
vector2.h:
template <typename T>
class GE_API Vector2
{
public:
T x;
T y;
// Indexation
T& operator [] (const size_t i);
const T& operator [] (const size_t i) const;
bool operator == (const Vector2& v) const;
bool operator != (const Vector2& v) const;
// Negation
const Vector2 operator - () const;
// Assignement
const Vector2& operator = (const Vector2& v);
const Vector2& operator += (const Vector2& v);
const Vector2& operator -= (const Vector2& v);
template <typename S>
const Vector2& operator *= (const S& s);
template <typename S>
const Vector2& operator /= (const S& s);
const Vector2 operator + (const Vector2& v) const;
const Vector2 operator + (const T& s) const;
const Vector2 operator - (const Vector2& v) const;
const Vector2 operator - (const T& s) const;
template <typename S>
const Vector2 operator * (const S& s) const;
const Vector2 operator * (const Vector2& v) const;
template <typename S>
const Vector2 operator / (const S& s) const;
const Vector2 operator / (const Vector2& v) const;
};
template <typename T>
GE_API const T dot(const Vector2<T>& a, const Vector2<T>& b);
template <typename T>
GE_API const T length(const Vector2<T>& v);
//..and other functionality
#include <vector2.inl>
Definitions of operators and functions are in separate file vector2.inl which is included in header file. GE_API is standard dllimport/export macro. Problem is that when I try to export this class and functions defined in vector2.h header file I'm getting errors on definitions of operators that definition of dllimport function is not allowed. Why is that and how to fix this?
I think in this case you don't need to specify dllimport/export for your class.
Because all source code will be avaliable to the user and only anoe thing that he heeds is to include vactor2.h header into his project.

Linking error with friend function in template class

I have a linking problem when using a home-made Complex class.
Class definition:
template<class T>
class Complex
{
public:
Complex(const T real = 0, const T imag = 0);
Complex(const Complex<T>& other);
~Complex(void) {};
Complex<T> operator*(const Complex<T>& other) const;
Complex<T> operator/(const Complex<T>& other) const;
Complex<T> operator+(const Complex<T>& other) const;
Complex<T> operator-(const Complex<T>& other) const;
friend void operator*=(const Complex<T>& z,const Complex<T>& other);
friend void operator/=(const Complex<T>& z,const Complex<T>& other);
friend void operator+=(const Complex<T>& z,const Complex<T>& other);
friend void operator-=(const Complex<T>& z,const Complex<T>& other);
void operator=(const Complex<T>& other);
friend T& real(Complex<T>& z);
friend T& imag(Complex<T>& z);
friend T abs(Complex<T>& z);
friend T norm(Complex<T>& z);
private:
T real_;
T imag_;
};
Implementation of abs:
template<class T>
T abs(Complex<T>& z)
{
return sqrt(z.real_*z.real_ + z.imag_*z.imag_);
}
I use the function abs like this : if(abs(z) <= 2).
Here are some errors I get:
Error 4 error LNK2001: unresolved external symbol "long double __cdecl abs(class Complex<long double> &)" (?abs##YAOAAV?$Complex#O###Z) C:\Users\Lucas\Documents\Visual Studio 2012\Projects\Fractals\Fractals\Main.obj Fractals
Error 3 error LNK2001: unresolved external symbol "long double & __cdecl imag(class Complex<long double> &)" (?imag##YAAAOAAV?$Complex#O###Z) C:\Users\Lucas\Documents\Visual Studio 2012\Projects\Fractals\Fractals\Main.obj Fractals
I get the same errors when using Complex<float> instead of Complex<long double>. I work with Visual C++ 2012. I would be really glad if you give me some hint on how to fix this. Thank you.
The function declared as
template <typename T>
class Complex {
// ...
friend T abs(Complex<T>& z);
// ...
};
is not a function template! It looks a bit like one as it is nested within a class template but that isn't quite enough. Here is what you probably meant to write:
template <typename T> class Complex;
template <typename T> T abs(Complex<T>&);
template <typename T>
class Complex {
// ...
friend T abs<T>(Complex<T>& z);
// ...
};
Alternatively, you could implement abs() when declaring it as friend.