questions about a header file

This is a header file I am trying to understand. I am 99.9% sure that anything in it is correct, as this was written by a top coder in my field (computational mathematics) and this header file has been used widely in the computational mathematics community. This header is kind of lengthy, but my questions are only concerned with a small portion of it. Please help me out.
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#ifndef  _VEC2T_HPP_
#define  _VEC2T_HPP_

#include "commoninc.hpp"

using std::istream;
using std::ostream;
using std::min;
using std::max;
using std::abs;

//-----------------------------------------------------------------------------------------------------
///Common VECtor Template
template <class F>
class Vec2T {
private:
  F _v[2];
public:
  enum{ X=0, Y=1 };
  //------------CONSTRUCTOR AND DESTRUCTOR 
  Vec2T()              { _v[0]=F(0);    _v[1]=F(0); }
  Vec2T(F f)           { _v[0]=f;       _v[1]=f; }
  Vec2T(const F* f)    { _v[0]=f[0];    _v[1]=f[1]; }
  Vec2T(F a,F b)       { _v[0]=a;       _v[1]=b; }
  Vec2T(const Vec2T& c){ _v[0]=c._v[0]; _v[1]=c._v[1]; }
  ~Vec2T() {}
  //------------POINTER and ACCESS
  operator F*()             { return &_v[0]; }
  operator const F*() const { return &_v[0]; }
  F* array()                { return &_v[0]; }  //access array
  F& operator()(int i)             { assert(i<2); return _v[i]; }
  const F& operator()(int i) const { assert(i<2); return _v[i]; }
  F& operator[](int i)             { assert(i<2); return _v[i]; }
  const F& operator[](int i) const { assert(i<2); return _v[i]; }
  F& x()             { return _v[0];}
  F& y()             { return _v[1];}
  const F& x() const { return _v[0];}
  const F& y() const { return _v[1];}
  //------------ASSIGN
  Vec2T& operator= ( const Vec2T& c ) { _v[0] =c._v[0]; _v[1] =c._v[1]; return *this; }
  Vec2T& operator+=( const Vec2T& c ) { _v[0]+=c._v[0]; _v[1]+=c._v[1]; return *this; }
  Vec2T& operator-=( const Vec2T& c ) { _v[0]-=c._v[0]; _v[1]-=c._v[1]; return *this; }
  Vec2T& operator*=( const F& s )     { _v[0]*=s;       _v[1]*=s;       return *this; }
  Vec2T& operator/=( const F& s )     { _v[0]/=s;       _v[1]/=s;       return *this; }
  //-----------LENGTH...
  F l1( void )     const  { F sum=F(0); for(int i=0; i<2; i++) sum=sum+abs(_v[i]); return sum; }
  F linfty( void ) const  { F cur=F(0); for(int i=0; i<2; i++) cur=max(cur,abs(_v[i])); return cur; }
  F l2( void )     const  { F sum=F(0); for(int i=0; i<2; i++) sum=sum+_v[i]*_v[i]; return sqrt(sum); }
  F length( void ) const  { return l2(); }
  Vec2T dir( void )    const  { F a=l2(); return (*this)/a; }
};

//-----------BOOLEAN OPS
template <class F> inline bool operator==(const Vec2T<F>& a, const Vec2T<F>& b) {
  bool res = true;  for(int i=0; i<2; i++)   res = res && (a(i)==b(i));  return res;
}
template <class F> inline bool operator!=(const Vec2T<F>& a, const Vec2T<F>& b) {
  return !(a==b);
}
template <class F> inline bool operator> (const Vec2T<F>& a, const Vec2T<F>& b) {
  bool res = true;  for(int i=0; i<2; i++)   res = res && (a(i)> b(i));  return res; 
}
template <class F> inline bool operator< (const Vec2T<F>& a, const Vec2T<F>& b) {
  bool res = true;  for(int i=0; i<2; i++)   res = res && (a(i)< b(i));  return res; 
}
template <class F> inline bool operator>=(const Vec2T<F>& a, const Vec2T<F>& b) {
  bool res = true;  for(int i=0; i<2; i++)	res = res && (a(i)>=b(i));  return res; 
}
template <class F> inline bool operator<=(const Vec2T<F>& a, const Vec2T<F>& b) {
  bool res = true;  for(int i=0; i<2; i++)   res = res && (a(i)<=b(i));  return res; 
}

//-----------NUMERICAL OPS
template <class F> inline Vec2T<F> operator- (const Vec2T<F>& a) {
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = -a[i]; return r;
}
template <class F> inline Vec2T<F> operator+ (const Vec2T<F>& a, const Vec2T<F>& b) {
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = a[i]+b[i]; return r; 
}
template <class F> inline Vec2T<F> operator- (const Vec2T<F>& a, const Vec2T<F>& b) {
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = a[i]-b[i]; return r;
}
template <class F> inline Vec2T<F> operator* (F scl, const Vec2T<F>& a) {
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = scl*a[i];  return r;
}
template <class F> inline Vec2T<F> operator* (const Vec2T<F>& a, F scl) {
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = scl*a[i];  return r;
}
template <class F> inline Vec2T<F> operator/ (const Vec2T<F>& a, F scl) {
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = a[i]/scl;  return r;
}

template <class F> inline F operator* (const Vec2T<F>& a, const Vec2T<F>& b) {
  F sum=F(0); for(int i=0; i<2; i++) sum=sum+a(i)*b(i); return sum;
}
template <class F> inline F dot       (const Vec2T<F>& a, const Vec2T<F>& b) {
  return a*b;
}
//-------------ew OPS
template <class F> inline Vec2T<F> min(const Vec2T<F>& a, const Vec2T<F>& b) {
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = min(a[i], b[i]); return r;
}
template <class F> inline Vec2T<F> max(const Vec2T<F>& a, const Vec2T<F>& b) {
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = max(a[i], b[i]); return r;
}
template <class F> inline Vec2T<F> abs(const Vec2T<F>& a) {
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = abs(a[i]); return r;
}
template <class F> inline Vec2T<F> ewmul(const Vec2T<F>&a, const Vec2T<F>& b) {
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = a[i]*b[i]; return r;
}
template <class F> inline Vec2T<F> ewdiv(const Vec2T<F>&a, const Vec2T<F>& b) { 
  Vec2T<F> r;  for(int i=0; i<2; i++) r[i] = a[i]/b[i]; return r;
}
//---------------INOUT
template <class F> istream& operator>>(istream& is, Vec2T<F>& a) {
  for(int i=0; i<2; i++) is>>a[i]; return is;
}
template <class F> ostream& operator<<(ostream& os, const Vec2T<F>& a) { 
  for(int i=0; i<2; i++) os<<a[i]<<" "; return os;
}

//---------------------------------------------------------
/// MOST COMMONLY USED
typedef Vec2T<double> Point2;
typedef Vec2T<int>    Index2;

#endif


Several questions about the section "POINTER and ACCESS":

1. In Line 28:
 
  operator F*()             { return &_v[0]; }


a.I suppose that an overloading operator should be defined in the following form:
 
type operator sign (parameters) {/*...*/}

But why are not these two operators defined with the type they are associated with? Why the type prior to the keyword "operator" is omitted???

b. The stuff between the keyword "operator" and the parentheses () should be the operator. Does this rule of thumb imply that the operator it is defining is actually "F*". In other words, F* is an operator?

2. What is the use of the second "const" in Line 29?
 
operator const F*() const { return &_v[0]; }


3. Each definition of operator in section "POINTER and ACCESS" has nothing to do with the class Vec2T. They are all about the type F. Why did the author of this header want to enclose these operator definitions in this header? I am wondering why he didn't put them at some other places of this projecct, instead of this header.


I appreciate any help and explanation. Thanks in advance.


Last edited on
1.a - Ignore what I said earlier This is a casting operator to F*. http://msdn.microsoft.com/en-us/library/ts48df3y%28v=vs.80%29.aspx
1.b it's called like this (F*)someVec2TInstance;
2. The "const" guarantees that the method will not alter the object, and thus allows the method to be called from constant instances.

3. "F" isn't an actual class, it's a template parameter for Vec2T. Read more about templates here:
http://cplusplus.com/doc/tutorial/templates/
Last edited on
1. What you see is a type casting operator and has this special syntax. These operators are called when the instance of the class is cast to the respective type. For example:

1
2
Vec2T<double> myV;
double *pDouble = (double*)myV; //This line calls operator double*(). 


2. You would have to read about const-correctness in C++. Basically, the second const keyword is telling the C++ compiler that the operator is safe to use on a constant object of type Vec2T. It is a promise that the operator will not change the object's internal state.

3. They have everything to do with the Vec2T class. Examine the return values: They come from the internal variable _v. Since those return values would be impossible from outside the class Vec2T, it is only possible to define these operators within the Vec2T class.
1)

you were on the right track with you 'b' response. F* is in fact the operator. This type of operator is called a casting operator. It allows for implicit conversions between the class and the cast type. So in this case, it allows you to cast from Vec2T<F> to F*:

1
2
Vec2T<int> foo;
int* ptr = foo;  // will be OK because of the casting operator 



2)

It means the function (or in this case the operator) is a const member. This allows it to be called with a const object.

Remember that const objects cannot call const member functions because they might alter the object's state.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class example
{
public:
  void Const() const { }  // a const member
  void NonConst() { } // a non-const member
};

const example c; // const object
example nc;  // non-const object


nc.Const();  // OK
nc.NonConst();  // OK

c.Const();  // OK
c.NonConst();  // Compiler error -- cannot call a non-const function with a const object 




3.

They all have to do with Vec2T.

The cast operators allow you to cast from Vec2T (as shown above)
The () operators allow you to access individual elements from a Vec2T
The [] operators apparently do the same thing as the () operators


So, the operators defined in that section are below:

1
2
3
4
5
Vec2T<int> o;
int* p = o;  // cast operator

int a = o[1];  // [] operator
int b = o(1);  // () operator 


As you can see, they all work with a Vec2T.


EDIT: double ninja'd =(
Last edited on
Hi hanst99,

Thanks a lot for your help! The link you gave regarding the casting operator seems to only discuss how to use casting operators, but not how to define a casting operator in a template (correct me if I am wrong). Do you know any tutorial on how to define a casting operator in a template environment?

Again, I appreciate!
Hi webJose,

Thank you very much for your explanation, which, combined with the help from hanst99 and Disch, really double powered!
Defining a type casting operator inside a template is no different from defining it in a regular, non-templated class. You just use the template's typename name, like F in the example instead of a fixed known type.

Any tutorial on defining type casting operators will do just fine.
Hi Disch,

Thank you so much for your help! For Point 1) you wrote, you mean that I don't have to convert the type explicitly by int* ptr = (int*)foo;, right?
Last edited on
That, and it makes that kind of cast safe.
Topic archived. No new replies allowed.