Templates and helpers.

  • Thread starter Magnus Jonneryd
  • Start date
M

Magnus Jonneryd

I want to be able to define a super class that defines some basic functionality
and also some helpers that define, mainly, arithmetic operations, but I've been
having some trouble.

The following example illustrates what i want to do:

template<typename T = int>
class A{};

template<typename T = int>
class B: public A<T>{};

template<typename T>
A<T> operator*(const A<T>& lhs, const A<T>& rhs){
return lhs;
}

int main(){
B<> b_1;
B<> b_2;
B<> b_3;
b_3 = b_1*b_2;
}

But when I compile it I get the following:
tst.cc: In function `int main()':
tst.cc:16: error: no match for 'operator=' in 'b_3 = operator* [with T
=int](((const A<int>&)((const A<int>*)((A<int>*)(&b_1)))), ((const A<int>&)
((const A<int>*)((A<int>*)(&b_2)))))'
tst.cc:5: note: candidates are: B<int>& B<int>::eek:perator=(const B<int>&)

Which I think means that the assignment operator ain't defined so that it's possible
to assign an instance of class A to class B. I was hoping that the inheritance would
make this possible, but alas.

What i then did was to define the operator as:
template<typename T>
T operator*(const T& lhs, const T& rhs){
return lhs;
}

Which works, but won't this cause a problem if i try multiplying something else
since this is quite a general solution? What I wanted to do was to be able to just
add some functionality in my sub-classes and be able to use the helpers that i
defined in the super class, and be able to use the same scheme with another
set of classes (i.e D: public D). But if i do that won't that mean that the two
functions will "collide"?

Thanks in advance.
 
V

Victor Bazarov

Magnus said:
I want to be able to define a super class that defines some basic functionality
and also some helpers that define, mainly, arithmetic operations, but I've been
having some trouble.

The following example illustrates what i want to do:

template<typename T = int>
class A{};

template<typename T = int>
class B: public A<T>{};

template<typename T>
A<T> operator*(const A<T>& lhs, const A<T>& rhs){
return lhs;
}

int main(){
B<> b_1;
B<> b_2;
B<> b_3;
b_3 = b_1*b_2;
}

But when I compile it I get the following:
tst.cc: In function `int main()':
tst.cc:16: error: no match for 'operator=' in 'b_3 = operator* [with T
=int](((const A<int>&)((const A<int>*)((A<int>*)(&b_1)))), ((const A<int>&)
((const A<int>*)((A<int>*)(&b_2)))))'
tst.cc:5: note: candidates are: B<int>& B<int>::eek:perator=(const B<int>&)

This isn't going to work even without templates. There is no assignment
operator in B that takes A as its argument.
Which I think means that the assignment operator ain't defined so that it's possible
to assign an instance of class A to class B.

Yep. Templates have nothing to do with it.
> I was hoping that the inheritance would
make this possible, but alas.

It never does.
What i then did was to define the operator as:
template<typename T>
T operator*(const T& lhs, const T& rhs){
return lhs;
}

Which works, but won't this cause a problem if i try multiplying something else
since this is quite a general solution?

Yes, any other user-defined type suddenly has operator* defined for it.
> What I wanted to do was to be able to just
add some functionality in my sub-classes and be able to use the helpers that i
defined in the super class, and be able to use the same scheme with another
set of classes (i.e D: public D). But if i do that won't that mean that the two
functions will "collide"?

I don't understand what functions will collide. If you define the
required assignment operator (and define it as doing the right thing),
what should collide with what?

V
 
M

Magnus Jonneryd

Victor said:
Magnus said:
I want to be able to define a super class that defines some basic
functionality and also some helpers that define, mainly, arithmetic
operations, but I've been having some trouble.

The following example illustrates what i want to do:

template<typename T = int>
class A{};

template<typename T = int>
class B: public A<T>{};

template<typename T>
A<T> operator*(const A<T>& lhs, const A<T>& rhs){
return lhs;
}

int main(){
B<> b_1;
B<> b_2;
B<> b_3;
b_3 = b_1*b_2;
}

But when I compile it I get the following:
tst.cc: In function `int main()':
tst.cc:16: error: no match for 'operator=' in 'b_3 = operator*
[with T =int](((const A<int>&)((const
A<int>*)((A<int>*)(&b_1)))), ((const A<int>&) ((const
A<int>*)((A<int>*)(&b_2)))))' tst.cc:5: note: candidates are:
B<int>& B<int>::eek:perator=(const B<int>&)

This isn't going to work even without templates. There is no assignment
operator in B that takes A as its argument.
Which I think means that the assignment operator ain't defined so that
it's possible to assign an instance of class A to class B.

Yep. Templates have nothing to do with it.
I was hoping that the inheritance would
make this possible, but alas.

It never does.
What i then did was to define the operator as:
template<typename T>
T operator*(const T& lhs, const T& rhs){
return lhs;
}

Which works, but won't this cause a problem if i try multiplying
something else since this is quite a general solution?

Yes, any other user-defined type suddenly has operator* defined for it.
What I wanted to do was to be able to just
add some functionality in my sub-classes and be able to use the helpers
that i defined in the super class, and be able to use the same scheme
with another set of classes (i.e D: public D). But if i do that won't
that mean that the two functions will "collide"?

I don't understand what functions will collide. If you define the
required assignment operator (and define it as doing the right thing),
what should collide with what?

V

Uhm, nevermind about the "collision" bit, I was just rambling. But as a
follow-up question: If i define an assignment operator, like so:

B<T> operator=(const A<T>& a){
if(this==&a)
return *this;

return B<T>(a);
}

How come it's possible to assign like this:
B<> b;
B<> b_1;
b = b_1;

As far as i can tell The class B inherits from A making it possible to make
the function call but since I don't know if it's the call: B = B or
B = A; I can't assign the extra information in B (if it's a case of B = B)
,on the left hand side, which means I loose some information every time i
use the operator. Is this correct or am I just rambling on again?

Thanks again.
 
V

Victor Bazarov

Magnus said:
[...] a
follow-up question: If i define an assignment operator, like so:

B<T> operator=(const A<T>& a){
if(this==&a)
return *this;

return B<T>(a);
}

How come it's possible to assign like this:
B<> b;
B<> b_1;
b = b_1;

As far as i can tell The class B inherits from A making it possible to make
the function call but since I don't know if it's the call: B = B or
B = A; I can't assign the extra information in B (if it's a case of B = B)
,on the left hand side, which means I loose some information every time i
use the operator. Is this correct or am I just rambling on again?

I don't know if you're rambling. Define the copy-assignment operator
and see which one is called when. Yes, you don't know whether the A<T>
is part of another B or of something completely different. That's why
A<T> is the only thing you can rely upon. The other stuff (data beyond
A<T> in 'this' B) has to either be kept as is (which is better) or
made up from scratch.

V
 
M

Magnus Jonneryd

Victor said:
Magnus said:
[...] a
follow-up question: If i define an assignment operator, like so:

B<T> operator=(const A<T>& a){
if(this==&a)
return *this;

return B<T>(a);
}

How come it's possible to assign like this:
B<> b;
B<> b_1;
b = b_1;

As far as i can tell The class B inherits from A making it possible to
make the function call but since I don't know if it's the call: B = B or
B = A; I can't assign the extra information in B (if it's a case of B =
B) ,on the left hand side, which means I loose some information every
time i use the operator. Is this correct or am I just rambling on again?

I don't know if you're rambling. Define the copy-assignment operator
and see which one is called when. Yes, you don't know whether the A<T>
is part of another B or of something completely different. That's why
A<T> is the only thing you can rely upon. The other stuff (data beyond
A<T> in 'this' B) has to either be kept as is (which is better) or
made up from scratch.

V

Thanks, I think that straightened it out.
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top