Help with operator overloading

Z

Zilla

I have the following simple program. I just want to be able to do math
operations (+, -, =)on Timer sublcasses, but want to handle cases
where either rhs or lhs is an intrinsic value, However, the compile
fails in my g++ 2.95 compiler during the 2nd to last line of the
main() with

template.cpp: In function `int main()':
template.cpp:24: `operator +<int>(int, const int &)' must have an
argument of class or enumerated type
template.cpp: In method `int & Timer::eek:perator +<int>(const int &)':
template.cpp:97: instantiated from here
template.cpp:42: request for member `_value' in `t', which is of non-
aggregate type `int'
template.cpp:43: static_cast from `Timer *' to `int *'

Seems like the operator+(T& t) function is being called, instead of
the operator+(int) function. Why?


#include <iostream.h>

class Timer {
template<class T>
friend T& operator+(const int value, const T& t);
public:
Timer();
~Timer();

template<class T>
T& operator+(const T& t);
template<class T>
T& operator+(const int value);
template<class T>
T& operator=(const T& t);
template<class T>
T& operator=(const int value);

int _value;
};

template<class T>
T& operator+(const int value, const T& t)
{
static T temp(value);
temp._value=t._value+value;
return temp;
}

Timer::Timer()
{
}

Timer::~Timer()
{
}

template<class T>
T& Timer::eek:perator+(const T& t)
{
// T* This=dynamic_cast<T*>(this);
this->_value+=t._value;
return *(static_cast<T*>(this));
}

template<class T>
T& Timer::eek:perator+(const int value)
{
T* This=dynamic_cast<T*>(this);
This->_value+=value;
return *This;
}

template<class T>
T& Timer::eek:perator=(const T& t)
{
T* This=dynamic_cast<T*>(this);
This->_value=t.value;
return *This;
}

template<class T>
T& Timer::eek:perator=(const int value)
{
T* This=dynamic_cast<T*>(this);
This->_value=value;
return *This;
}

class tRCD : public Timer {
public:
tRCD(const int value);
~tRCD();
};

tRCD::tRCD(const int value)
{
_value=value;
}

tRCD::~tRCD()
{
}

int main()
{
tRCD trcd1(1);
cout << "trcd1._value: " << trcd1._value << endl;
tRCD trcd2(2);
cout << "trcd2._value: " << trcd2._value << endl;
trcd1=trcd1+trcd2;
cout << "trcd1._value: " << trcd1._value << endl;
trcd1=1+trcd1;
cout << "trcd1._value: " << trcd1._value << endl;
trcd1=5;
cout << "trcd1._value: " << trcd1._value << endl;
// trcd1.operator=(trcd1.operator+(1));
trcd1=trcd1+1;
cout << "trcd1._value: " << trcd1._value << endl;
return 0;
}
 
V

Victor Bazarov

Zilla said:
I have the following simple program. I just want to be able to do math
operations (+, -, =)on Timer sublcasses, but want to handle cases
where either rhs or lhs is an intrinsic value, However, the compile
fails in my g++ 2.95 compiler during the 2nd to last line of the
main() with

template.cpp: In function `int main()':
template.cpp:24: `operator +<int>(int, const int &)' must have an
argument of class or enumerated type
template.cpp: In method `int & Timer::eek:perator +<int>(const int &)':
template.cpp:97: instantiated from here
template.cpp:42: request for member `_value' in `t', which is of non-
aggregate type `int'
template.cpp:43: static_cast from `Timer *' to `int *'

Seems like the operator+(T& t) function is being called, instead of
the operator+(int) function. Why?


#include <iostream.h>

There is no such standard header. Try said:
class Timer {
template<class T>
friend T& operator+(const int value, const T& t);
public:
Timer();
~Timer();

template<class T>
T& operator+(const T& t);

Since 'T' is the argument, you can expect that 't' would be
deduced from the argument when you add something to a Timer,
so this one is OK.
template<class T>
T& operator+(const int value);

Here, 'T' is only the return value. WHY? How do you expect
to use this operator? The lhs is 'Timer'. The rhs is 'int'.
Where would T come from?
template<class T>
T& operator=(const T& t);

OK, I can understand that assigning from some type should be
possible. But why do you make the return value 'T&' instead of
'Timer&'?
template<class T>
T& operator=(const int value);

Now, this looks bogus, sorry. Assign to a timer from an 'int'
and return some other value? How do you even get 'T' to factor
into your expression when you write

Timer t;
t = 42; // what's T here?

???
int _value;
};

template<class T>
T& operator+(const int value, const T& t)
{
static T temp(value);
temp._value=t._value+value;
return temp;
}

Timer::Timer()
{
}

Timer::~Timer()
{
}

template<class T>
T& Timer::eek:perator+(const T& t)
{
// T* This=dynamic_cast<T*>(this);
this->_value+=t._value;
return *(static_cast<T*>(this));
}

template<class T>
T& Timer::eek:perator+(const int value)
{
T* This=dynamic_cast<T*>(this);
This->_value+=value;
return *This;
}

template<class T>
T& Timer::eek:perator=(const T& t)
{
T* This=dynamic_cast<T*>(this);
This->_value=t.value;
return *This;
}

template<class T>
T& Timer::eek:perator=(const int value)
{
T* This=dynamic_cast<T*>(this);
This->_value=value;
return *This;
}

class tRCD : public Timer {
public:
tRCD(const int value);
~tRCD();
};

tRCD::tRCD(const int value)
{
_value=value;
}

tRCD::~tRCD()
{
}

int main()
{
tRCD trcd1(1);
cout << "trcd1._value: " << trcd1._value << endl;
tRCD trcd2(2);
cout << "trcd2._value: " << trcd2._value << endl;
trcd1=trcd1+trcd2;
cout << "trcd1._value: " << trcd1._value << endl;
trcd1=1+trcd1;
cout << "trcd1._value: " << trcd1._value << endl;
trcd1=5;
cout << "trcd1._value: " << trcd1._value << endl;
// trcd1.operator=(trcd1.operator+(1));
trcd1=trcd1+1;
cout << "trcd1._value: " << trcd1._value << endl;
return 0;
}

Could you explain what exactly it is you're trying to
accomplish?

V
 
J

Jim Langston

Zilla said:
I have the following simple program. I just want to be able to do math
operations (+, -, =)on Timer sublcasses, but want to handle cases
where either rhs or lhs is an intrinsic value, However, the compile
fails in my g++ 2.95 compiler during the 2nd to last line of the
main() with

template.cpp: In function `int main()':
template.cpp:24: `operator +<int>(int, const int &)' must have an
argument of class or enumerated type
template.cpp: In method `int & Timer::eek:perator +<int>(const int &)':
template.cpp:97: instantiated from here
template.cpp:42: request for member `_value' in `t', which is of non-
aggregate type `int'
template.cpp:43: static_cast from `Timer *' to `int *'

Seems like the operator+(T& t) function is being called, instead of
the operator+(int) function. Why?


#include <iostream.h>

class Timer {
template<class T>
friend T& operator+(const int value, const T& t);
public:
Timer();
~Timer();

template<class T>
T& operator+(const T& t);
template<class T>
T& operator+(const int value);
template<class T>
T& operator=(const T& t);
template<class T>
T& operator=(const int value);

int _value;
};

template<class T>
T& operator+(const int value, const T& t)

template.cpp:24: `operator +<int>(int, const int &)' must have an
argument of class or enumerated type

Here it winds up being ( int, const int& t)
which is what the error is about. Apparently you can't override int + int
(which makes sense).
{
static T temp(value);
temp._value=t._value+value;
return temp;
}

Timer::Timer()
{
}

Timer::~Timer()
{
}

template<class T>
T& Timer::eek:perator+(const T& t)
{
// T* This=dynamic_cast<T*>(this);
this->_value+=t._value;

template.cpp:42: request for member `_value' in `t', which is of non-
aggregate type `int'

Parm is const int& t.
Then you cast this to an int*.
an int does not have a ._value member
return *(static_cast<T*>(this));

template.cpp:43: static_cast from `Timer *' to `int *'

a Timer* is not an int* and it's bitching.
}

template<class T>
T& Timer::eek:perator+(const int value)
{
T* This=dynamic_cast<T*>(this);
This->_value+=value;
return *This;
}

template<class T>
T& Timer::eek:perator=(const T& t)
{
T* This=dynamic_cast<T*>(this);
This->_value=t.value;
return *This;
}

template<class T>
T& Timer::eek:perator=(const int value)
{
T* This=dynamic_cast<T*>(this);
This->_value=value;
return *This;
}

class tRCD : public Timer {
public:
tRCD(const int value);
~tRCD();
};

tRCD::tRCD(const int value)
{
_value=value;
}

tRCD::~tRCD()
{
}

int main()
{
tRCD trcd1(1);
cout << "trcd1._value: " << trcd1._value << endl;
tRCD trcd2(2);
cout << "trcd2._value: " << trcd2._value << endl;
trcd1=trcd1+trcd2;
cout << "trcd1._value: " << trcd1._value << endl;
trcd1=1+trcd1;
cout << "trcd1._value: " << trcd1._value << endl;
trcd1=5;
cout << "trcd1._value: " << trcd1._value << endl;
// trcd1.operator=(trcd1.operator+(1));
trcd1=trcd1+1;
cout << "trcd1._value: " << trcd1._value << endl;
return 0;
}

Fix the errors.
 
Z

Zilla

Could you explain what exactly it is you're trying to
accomplish?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -

I want to program regular math expressions (*,/,+,=, etc...) for
objects of type Timers, and its sub-classes. So...

class Timer {
operator-blah(...)
};

class tRCD : public Timer {
blah();
};

class tRP : public Timer {
blah();
};

int main()
{
tRCD trcd1;
tRCD trcd2;
tRP trp;
trcd1=trcd1+1;
trcd1=2*trcd2;
trcd1=trcd1+2+trcd2;
}

IOW, I want the operations in Timer, but need to return the sub-class
type, on the fly...
 
V

Victor Bazarov

Zilla said:
I want to program regular math expressions (*,/,+,=, etc...) for
objects of type Timers, and its sub-classes. So...

class Timer {
operator-blah(...)
};

class tRCD : public Timer {
blah();
};

class tRP : public Timer {
blah();
};

int main()
{
tRCD trcd1;
tRCD trcd2;
tRP trp;
trcd1=trcd1+1;
trcd1=2*trcd2;
trcd1=trcd1+2+trcd2;
}

IOW, I want the operations in Timer, but need to return the sub-class
type, on the fly...

Ah.. I see. So, what book are you currently reading?

....Alright, that wasn't necessarily the right question. But I think
you shouldn't attempt such high flying without getting stable on the
runway yet, so to speak.

Forget the derived classes for now. What do you need to do to make
your class work well in an expression (sometimer + 1) *and* in another
expression like (2 * sometimer)? Good books teach us to make the
operators non-members (otherwise the '2*blah' is not going to work
even if we have the needed converting constructor).

Now, the trouble is that if you have them as non-members, how do we
make them work with derived classes? Your thought was in the right
direction, use templates. But then what, right? Then each of the
function templates should call the class' virtual function to add
an int or multiply with an int. Something like

class Timer {
...
virtual Timer add(int) const;
};

template<class Tm> Tm operator+(Tm const& tm, int i) {
return tm.add(i);
}

template<class Tm> Tm operator+(int i, Tm const& tm) {
return tm+i;
}

class Timer2 : public Timer {
virtual Timer add(int) const; // return value?
};

But now the problem is that 'Timer2::add' function does not return
the right type. It should return 'Timer2', right? What to do
about that?

Here you should probably implement += (which should return the same
object by reference), and you can make the derived class return
the covariant type (itself). But you will have to overload the
operator+= for the derived type as well. You don't sound like you
want to do that.

Another possibility is to let the operators always return 'Timer'
and make sure that the derived classes can assign from it:

class Timer4 : public Timer {
...
Timer4& operator=(Timer const&);
};

In any case, what I see here is a bit incomplete design. It is
not clear what functionality the 'Timer' class should have because
it's unclear what should the operations you presented here to do.

V
 
Z

Zilla

Zillawrote:







Ah.. I see. So, what book are you currently reading?

...Alright, that wasn't necessarily the right question. But I think
you shouldn't attempt such high flying without getting stable on the
runway yet, so to speak.

Forget the derived classes for now. What do you need to do to make
your class work well in an expression (sometimer + 1) *and* in another
expression like (2 * sometimer)? Good books teach us to make the
operators non-members (otherwise the '2*blah' is not going to work
even if we have the needed converting constructor).

Now, the trouble is that if you have them as non-members, how do we
make them work with derived classes? Your thought was in the right
direction, use templates. But then what, right? Then each of the
function templates should call the class' virtual function to add
an int or multiply with an int. Something like

class Timer {
...
virtual Timer add(int) const;
};

template<class Tm> Tm operator+(Tm const& tm, int i) {
return tm.add(i);
}

template<class Tm> Tm operator+(int i, Tm const& tm) {
return tm+i;
}

class Timer2 : public Timer {
virtual Timer add(int) const; // return value?
};

But now the problem is that 'Timer2::add' function does not return
the right type. It should return 'Timer2', right? What to do
about that?

Here you should probably implement += (which should return the same
object by reference), and you can make the derived class return
the covariant type (itself). But you will have to overload the
operator+= for the derived type as well. You don't sound like you
want to do that.

Another possibility is to let the operators always return 'Timer'
and make sure that the derived classes can assign from it:

class Timer4 : public Timer {
...
Timer4& operator=(Timer const&);
};

In any case, what I see here is a bit incomplete design. It is
not clear what functionality the 'Timer' class should have because
it's unclear what should the operations you presented here to do.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask- Hide quoted text -

- Show quoted text -

Thanks for your help...

I've been reading the following books and articles - you're correct,
templates are NOT appetizers.
- C++ Primer (Lippman & Lajoie)
- Modern C++ Design (Alexandrescu)
- http://www.hackcraft.net/cpp/templateInheritance
- http://polar.ncep.noaa.gov/mmab/papers/tn185/node7.html


Yes I do NOT want to overload any of the operator-blah functions in my
derived classes, that's the whole point of this excercise. I want to
Timer to implement ALL of them, and the Timer derived classes to
inherit them, but return the correct derived class type. I've used
templates before, but just as containers so I'm not new to the
concept, just new to the concept of temlates AND inheritance. One
thing I'm playing with, is since all my timer "values" will ultimately
of type double, I'm using double as my return type for the functions,
except for operator=(), which still has to return the derived class
type of courxe. IOW,

tRCD trcd;
trcd=trcd+2+trcd;
is...
trcd.operator=(trcd.operator+(operator(2, trcd);
....so if the right-most operator returns a double, the next operator+
() will work, which would also return a double, but the last
operator=() MUST return a tRCD type.
 
V

Victor Bazarov

Zilla said:
[..] I do NOT want to overload any of the operator-blah functions in my
derived classes, that's the whole point of this excercise. I want to
Timer to implement ALL of them, and the Timer derived classes to
inherit them, but return the correct derived class type. I've used
templates before, but just as containers so I'm not new to the
concept, just new to the concept of temlates AND inheritance. One
thing I'm playing with, is since all my timer "values" will ultimately
of type double, I'm using double as my return type for the functions,
except for operator=(), which still has to return the derived class
type of courxe. IOW,

tRCD trcd;
trcd=trcd+2+trcd;
is...
trcd.operator=(trcd.operator+(operator(2, trcd);

I believe you missed one + and a couple of parens:

trcd.operator=(trcd.operator+(operator+(2, trcd)));

(but I think I get the idea).
...so if the right-most operator returns a double, the next operator+
() will work, which would also return a double, but the last
operator=() MUST return a tRCD type.

OK, let's examine this...

Let's say we use templates to make the return value type correct, OK?

#include <iostream>

template<class D>
class A { // base that implements "everything"
int value;
public:
A(int v) : value(v) {}
D add(int) const;
D add(A const&) const;
};

template<class D>
D operator+(int i, A<D> const& d) {
return d.add(i);
}

template<class D>
D operator+(A<D> const& a, int i) {
return a.add(i);
}

template<class D>
D operator+(A<D> const& a, A<D> const& aa) {
return a.add(aa);
}

class D1 : public A<D1> { // derived one
public:
// constructors are not inherited, so you need one here
D1(int v) : A<D1>(v) {}
};

class D2 : public A<D2> { // derived two
public:
// constructors are not inherited, so you need one here
D2(int v) : A<D2>(v) {}
};

// Now, the hard part is how to implement the 'add' member in A
template:

template<class D>
D A<D>::add(int i) const
{
D d(this->value + i); // ???
return d;
}

template<class D>
D A<D>::add(A<D> const& a) const
{
return add(a.value);
}

int main()
{
D1 d1(42), d11(4242);
D2 d2(666), d22(6666);

d11 = d11 + 5;// + d1;
d22 = d22 + 7;// + d2;
return 0;
}

Would that work? Use it as a starting point.

V
 
Z

Zilla

Zillawrote:
[..] I do NOT want to overload any of the operator-blah functions in my
derived classes, that's the whole point of this excercise. I want to
Timer to implement ALL of them, and the Timer derived classes to
inherit them, but return the correct derived class type. I've used
templates before, but just as containers so I'm not new to the
concept, just new to the concept of temlates AND inheritance. One
thing I'm playing with, is since all my timer "values" will ultimately
of type double, I'm using double as my return type for the functions,
except for operator=(), which still has to return the derived class
type of courxe. IOW,
tRCD trcd;
trcd=trcd+2+trcd;
is...
trcd.operator=(trcd.operator+(operator(2, trcd);

I believe you missed one + and a couple of parens:

trcd.operator=(trcd.operator+(operator+(2, trcd)));

(but I think I get the idea).
...so if the right-most operator returns a double, the next operator+
() will work, which would also return a double, but the last
operator=() MUST return a tRCD type.

OK, let's examine this...

Let's say we use templates to make the return value type correct, OK?

#include <iostream>

template<class D>
class A { // base that implements "everything"
int value;
public:
A(int v) : value(v) {}
D add(int) const;
D add(A const&) const;
};

template<class D>
D operator+(int i, A<D> const& d) {
return d.add(i);
}

template<class D>
D operator+(A<D> const& a, int i) {
return a.add(i);
}

template<class D>
D operator+(A<D> const& a, A<D> const& aa) {
return a.add(aa);
}

class D1 : public A<D1> { // derived one
public:
// constructors are not inherited, so you need one here
D1(int v) : A<D1>(v) {}
};

class D2 : public A<D2> { // derived two
public:
// constructors are not inherited, so you need one here
D2(int v) : A<D2>(v) {}
};

// Now, the hard part is how to implement the 'add' member in A
template:

template<class D>
D A<D>::add(int i) const
{
D d(this->value + i); // ???
return d;
}

template<class D>
D A<D>::add(A<D> const& a) const
{
return add(a.value);
}

int main()
{
D1 d1(42), d11(4242);
D2 d2(666), d22(6666);

d11 = d11 + 5;// + d1;
d22 = d22 + 7;// + d2;
return 0;
}

Would that work? Use it as a starting point.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask- Hide quoted text -

- Show quoted text -

Thanks, so far it worked for these test cases. It's scary how the
compiler knows how to implement the "=" operation. I'll code it so as
NOT to leave it to chance.

int main()
{
D1 d33(1);
D1 d22(1);
D1 d11=d33;
cout << "d11.value: " << d11.getVal() << endl;
d11=1;
cout << "d11.value: " << d11.getVal() << endl;
d11 = d11 + 1;
cout << "d11.value: " << d11.getVal() << endl;
d11 = 1 + d11;
cout << "d11.value: " << d11.getVal() << endl;
d11 = d22 + d11;
cout << "d11.value: " << d11.getVal() << endl;
return 0;
}
 
V

Victor Bazarov

Zilla said:
[..]

class D1 : public A<D1> { // derived one
public:
// constructors are not inherited, so you need one here
D1(int v) : A<D1>(v) {}
};

class D2 : public A<D2> { // derived two
public:
// constructors are not inherited, so you need one here
D2(int v) : A<D2>(v) {}
};
[..]

Would that work? Use it as a starting point.

V

Thanks, so far it worked for these test cases. It's scary how the
compiler knows how to implement the "=" operation. I'll code it so as
NOT to leave it to chance.

int main()
{
D1 d33(1);
D1 d22(1);
D1 d11=d33;
cout << "d11.value: " << d11.getVal() << endl;
d11=1;
cout << "d11.value: " << d11.getVal() << endl;
d11 = d11 + 1;
cout << "d11.value: " << d11.getVal() << endl;
d11 = 1 + d11;
cout << "d11.value: " << d11.getVal() << endl;
d11 = d22 + d11;
cout << "d11.value: " << d11.getVal() << endl;
return 0;
}

Just to bring it to your attention: it is important to not get the
types mixed up when copy-pasting your code. The class 'D1' is
defined as deriving from 'A<D1>' and 'D2' is from 'A<D2>'. This
is known as CRTP, IIRC. If when you define some 'D3' you make it
derive from 'A<D2>', the stuff can start going wrong and it might
be difficult to find. Or maybe not... Good luck!

V
 
Z

Zilla

Zilla said:
[..]
class D1 : public A<D1> { // derived one
public:
// constructors are not inherited, so you need one here
D1(int v) : A<D1>(v) {}
};
class D2 : public A<D2> { // derived two
public:
// constructors are not inherited, so you need one here
D2(int v) : A<D2>(v) {}
};
[..]
Would that work? Use it as a starting point.
V
Thanks, so far it worked for these test cases. It's scary how the
compiler knows how to implement the "=" operation. I'll code it so as
NOT to leave it to chance.
int main()
{
D1 d33(1);
D1 d22(1);
D1 d11=d33;
cout << "d11.value: " << d11.getVal() << endl;
d11=1;
cout << "d11.value: " << d11.getVal() << endl;
d11 = d11 + 1;
cout << "d11.value: " << d11.getVal() << endl;
d11 = 1 + d11;
cout << "d11.value: " << d11.getVal() << endl;
d11 = d22 + d11;
cout << "d11.value: " << d11.getVal() << endl;
return 0;
}

Just to bring it to your attention: it is important to not get the
types mixed up when copy-pasting your code. The class 'D1' is
defined as deriving from 'A<D1>' and 'D2' is from 'A<D2>'. This
is known as CRTP, IIRC. If when you define some 'D3' you make it
derive from 'A<D2>', the stuff can start going wrong and it might
be difficult to find. Or maybe not... Good luck!

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask- Hide quoted text -

- Show quoted text -

Thanks. Yes I noticed this right off. I'm playing with this code now,
and even trying out the straight-forward use of the template, ie,
without the class declarations inheritting the template.

class D1 {
blah()
};

class D2 {
blah()
};

int main()
{
A<D1> d1;
A<D2> d2;
d1=blah...
}
 
Z

Zilla

Zillawrote:
[..]
class D1 : public A<D1> { // derived one
public:
// constructors are not inherited, so you need one here
D1(int v) : A<D1>(v) {}
};
class D2 : public A<D2> { // derived two
public:
// constructors are not inherited, so you need one here
D2(int v) : A<D2>(v) {}
};
[..]
Would that work? Use it as a starting point.
V
Thanks, so far it worked for these test cases. It's scary how the
compiler knows how to implement the "=" operation. I'll code it so as
NOT to leave it to chance.
int main()
{
D1 d33(1);
D1 d22(1);
D1 d11=d33;
cout << "d11.value: " << d11.getVal() << endl;
d11=1;
cout << "d11.value: " << d11.getVal() << endl;
d11 = d11 + 1;
cout << "d11.value: " << d11.getVal() << endl;
d11 = 1 + d11;
cout << "d11.value: " << d11.getVal() << endl;
d11 = d22 + d11;
cout << "d11.value: " << d11.getVal() << endl;
return 0;
}
Just to bring it to your attention: it is important to not get the
types mixed up when copy-pasting your code. The class 'D1' is
defined as deriving from 'A<D1>' and 'D2' is from 'A<D2>'. This
is known as CRTP, IIRC. If when you define some 'D3' you make it
derive from 'A<D2>', the stuff can start going wrong and it might
be difficult to find. Or maybe not... Good luck!
- Show quoted text -

Thanks. Yes I noticed this right off. I'm playing with this code now,
and even trying out the straight-forward use of the template, ie,
without the class declarations inheritting the template.

class D1 {
blah()

};

class D2 {
blah()

};

int main()
{
A<D1> d1;
A<D2> d2;
d1=blah...



}- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -

Ok, I was having problems with your example, so I went back to basics.
I stripped it down to the following code for operator=() only. I can't
even get it to compile...
g++ -c timers.cpp
timers.cpp: In function `int main()':
timers.cpp:35: no match for `tRCD & = double'
timers.cpp:30: candidates are: class tRCD & tRCD::eek:perator =(const
tRCD &)

Why isn't the Timer<T>::eek:perator=(...) being seen?

#include <iostream>

////////////////////////////////////////////////////////
// Base class that defines ALL the operations
template<class T>
class Timer {
public:
Timer();
T& operator=(const double v);

double _min;
};

template<class T>
Timer<T>::Timer() : _min(0)
{
}

template<class T>
T& Timer<T>::eek:perator=(const double v)
{
// do something
}

class tRCD : public Timer<tRCD> {
public:
tRCD() : Timer<tRCD>() {}
~tRCD() {}
};

int main()
{
tRCD t1;
t1=3.0;
cout << "t1.min: " << t1._min << endl;
}
 
V

Victor Bazarov

Zilla said:
Zillawrote:
On Mar 22, 4:06 pm, "Victor Bazarov" <[email protected]>
wrote:
[..]
class D1 : public A<D1> { // derived one
public:
// constructors are not inherited, so you need one here
D1(int v) : A<D1>(v) {}
};
class D2 : public A<D2> { // derived two
public:
// constructors are not inherited, so you need one here
D2(int v) : A<D2>(v) {}
};
[..]
Would that work? Use it as a starting point.

Thanks, so far it worked for these test cases. It's scary how the
compiler knows how to implement the "=" operation. I'll code it so
as NOT to leave it to chance.
int main()
{
D1 d33(1);
D1 d22(1);
D1 d11=d33;
cout << "d11.value: " << d11.getVal() << endl;
d11=1;
cout << "d11.value: " << d11.getVal() << endl;
d11 = d11 + 1;
cout << "d11.value: " << d11.getVal() << endl;
d11 = 1 + d11;
cout << "d11.value: " << d11.getVal() << endl;
d11 = d22 + d11;
cout << "d11.value: " << d11.getVal() << endl;
return 0;
}
Just to bring it to your attention: it is important to not get the
types mixed up when copy-pasting your code. The class 'D1' is
defined as deriving from 'A<D1>' and 'D2' is from 'A<D2>'. This
is known as CRTP, IIRC. If when you define some 'D3' you make it
derive from 'A<D2>', the stuff can start going wrong and it might
be difficult to find. Or maybe not... Good luck!
- Show quoted text -

Thanks. Yes I noticed this right off. I'm playing with this code now,
and even trying out the straight-forward use of the template, ie,
without the class declarations inheritting the template.

class D1 {
blah()

};

class D2 {
blah()

};

int main()
{
A<D1> d1;
A<D2> d2;
d1=blah...



}- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -

Ok, I was having problems with your example, so I went back to basics.
I stripped it down to the following code for operator=() only. I can't
even get it to compile...
g++ -c timers.cpp
timers.cpp: In function `int main()':
timers.cpp:35: no match for `tRCD & = double'
timers.cpp:30: candidates are: class tRCD & tRCD::eek:perator =(const
tRCD &)

Why isn't the Timer<T>::eek:perator=(...) being seen?

#include <iostream>

////////////////////////////////////////////////////////
// Base class that defines ALL the operations
template<class T>
class Timer {
public:
Timer();
T& operator=(const double v);

double _min;
};

template<class T>
Timer<T>::Timer() : _min(0)
{
}

template<class T>
T& Timer<T>::eek:perator=(const double v)
{
// do something
}

class tRCD : public Timer<tRCD> {
public:
tRCD() : Timer<tRCD>() {}
~tRCD() {}
};

int main()
{
tRCD t1;
t1=3.0;
cout << "t1.min: " << t1._min << endl;
}

The assignment operator from the base class is hidden by the
assignment operator from the derived class. You need to add
a line with 'using' in it to the 'tRCD' class.

The next thing is to decide what your Timer<T>::eek:perator=
is going to return. I am not sure how you're going to handle
that, since you can't really return *this (the usual value
returned from the assignment op).

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top