operator overloading

Hello all, the code below is a vector class which is a child of the STL vector class. The code below will generate an error when doing this in the main function:

Vec<double> d = 2*x,

since 2 can be understood as an integer or double. If I do the following:

Vec<double> d = 2.0*x

will be ok, since 2.0 is a double.

Can anyone tell me how can I fix my code, so that when one does any of the above two lines no error appears and of course the result is correct? That is, i want that this

Vec<double> d = 2*x
or
Vec<double> d = 2.0*x

can be done without errors.

Thanks.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <iostream>
#include <vector>
using namespace std;  

template <class T>
class Vec : public vector<T> 
{
public:
  // constructors
  Vec();
  Vec(int length); 
  Vec(int length, T typeValue); 
  Vec(const Vec<T>& rhsObj); 
  const Vec<T>& operator=(const Vec<T>& rhsObj);
  const Vec<T>& operator=(T& typeValue);
  const Vec<T>& operator*=(T typeVal);
  const Vec<T> operator*(T typeVal) const;
  ~Vec();
};


template<class T> 
Vec<T>::
Vec() : vector<T>()
{ 
}

template<class T> 
Vec<T>::
Vec(int length) : vector<T>(length)
{
}

template<class T> 
Vec<T>::
Vec(int length, T typeValue) : vector<T>(length,typeValue)
{
}

template<class T> 
Vec<T>::
Vec(const Vec<T>& rhsObj) : vector<T>(rhsObj)
{
}

template<class T> 
const Vec<T>& 
Vec<T>::
operator=(const Vec<T>& rhsObj)
{
  vector<T>::operator =(rhsObj);
  return *this;
}

template<class T> 
const Vec<T>& 
Vec<T>::
operator=(T& typeValue)
{
  for (int i = 0; i < this->size(); i++)
    (*this)[i] = typeValue;
  return *this;
}

template<class T>
const Vec<T>&
Vec<T>::
operator*=(T typeVal)
{                              
  for (unsigned i = 0; i < this->size(); i++)
    (*this)[i] *= typeVal; 

  return *this;
} 

template<class T>
const Vec<T>
Vec<T>::
operator*(T typeVal) const
{
  return (Vec<T>(*this) *= typeVal);
} 

template<class T> 
Vec<T>::
~Vec()
{
}

// ******************************************************************************
// overloading externally since the first argument is not an object: typeVal*obj1
// ******************************************************************************
template<class T>
const Vec<T>
operator*(const T typeVal, const Vec<T>& obj1)
{
  return (obj1*typeVal);
}


int main()
{
  Vec<double> x(3,4);
  Vec<double> d = 2*x;
  cout << d[0] << " " << d[1] << " " << d[2] << endl;
  return 0;
}
Make the length constructor explicit.
1. std::vector isn't prepared to be inherited from.
2. Have you tried x*2?
Yes, I also have * overloaded as a member function in my full code (not shown above). In that case I can do x*2 or x*2.0 without problems ... I think because 2 is automatically converted to double. With the approach in the code shown above, I wanted to compute in the inverse order, that is: 2*x, this way I could do it in both ways, x*2 or 2*x.
thanks both.

1) I don't see why should I use explicit in the length constructor. can you explian more?

2) My full code has also other functions and i don't have problems with the heritage from std::vector class? can you explian what also could go wrong if i use std::vector as the parent class?

In response to 1):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Thing {
private:
    std::string stuff;
public:
    Thing();
    explicit Thing(int);
    Thing(std::string);
}

Thing::Thing() : stuff()
{
}

Thing::Thing(int data) {
    //do stuff with int...
}

Thing::Thing(std::string data) {
    //do stuff with string...
}

int main() {
    int a = 0;
    std::string b = "data";
    Thing something; //works
    Thing something2(a); //works
    //Thing something3 = a; //does not work, the int constructor must be explicitly called like the above
    Thing something4(b); //works
    Thing something5 = b; //works, same as something4
    return 0;
}
Helios,

Ok. I see the point. Now, I have changed the code, so now the functions are overloaded as free functions. The code is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <vector>
using namespace std; 

template<class T>
const vector<T>&
operator*=(vector<T>& obj1, const T typeVal)
{                              
  for (unsigned i = 0; i < obj1.size(); i++)
    obj1[i] *= typeVal; 

  return obj1;
} 

template<class T>
const vector<T>
operator*(const vector<T>& obj1, const T typeVal)
{
  return (vector<T>(obj1) *= typeVal);
} 

template<class T>
const vector<T>
operator*(const T typeVal, const vector<T>& obj1)
{
  return (obj1*typeVal);
}

int main()
{
  vector<double> x(3,4);
  vector<double> d = x*2.0;
  cout << d[0] << " " << d[1] << " " << d[2] << endl;
  return 0;
}


Further questions:

1)Now, my problem is twofold: I have to explicitly use 2.0*x and x*2.0. Is there any way that the code works fine independently if I use 2 or 2.0? Also, one point that it is important to me. This modified code works fine under MVS, but it won't work under GNU compiler. That is, if I use g++ main.cpp, it will produce an error because there is no *= that matches the overloaded operators in std::vector class. How can i make it so that it can also be built in the GNU compiler?

2) How can I overload (), so that I can use it as x(i) rather than x[i]? I tried to do it overlading () as a free function but the compiler complains that () must be a non-static member.

Last edited on
1) Perhaps this does more than you want:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <vector>
using namespace std; 

// The original template<class T> version is no longer needed, thus removed

template<class T, class U>
const vector<T>& operator*(vector<T>& obj1, const U typeVal)
{
	for (unsigned i = 0; i < obj1.size(); i++)
		obj1[i] *= typeVal; 
	return obj1;  
} 

template<class T, class U>
const vector<T>& operator*(const U typeVal, vector<T>& obj1)
{
	return (obj1 * typeVal);
} 

int main()
{
  vector<double> x(3,4);
  vector<double> d = x * 2.0;
  vector<double> x2(3,4);
  vector<double> d2 = x2 * 2;
  vector<double> x3(3,4);
  vector<double> d3 = 2 * x3;
  vector<double> x4(3,4);
  vector<double> d4 = x4 * 2.2;
  vector<double> x5(3,4);
  vector<double> d5 = 2.3 * x5;

  cout << d[0] << " " <<  d[1] << " " <<  d[2] << endl;
  cout << d2[0] << " " << d2[1] << " " << d2[2] << endl;
  cout << d3[0] << " " << d3[1] << " " << d3[2] << endl;
  cout << d4[0] << " " << d4[1] << " " << d4[2] << endl;
  cout << d5[0] << " " << d5[1] << " " << d5[2] << endl;
  return 0;
}


It works as long as type U can be implicitly converted to type T (e.g., from int to double).
Last edited on
I see. Thanks. I am thinking in doing a wrapper to the std::vector (i have posted part of the code here: http://www.cplusplus.com/forum/general/13931/ ). What do you think is better? doing the above code or doing the wrapper?

Thanks.
Last edited on
the wrapper is probably a better approach, but also a lot more work (you have to make iterators, etc.)
Topic archived. No new replies allowed.