I have a class "Homework" that has a private attribute "int time" and I have set up a + operator to add the times of two Object instances. I have also created a Template "sum(T a, T b)" that takes two arguments and adds them together.

I'm having difficulty using my "Homework" objects as arguments in my sum() template function. Any obvious reasons why my template breaks?

//code for my template declaration & definition
template <class T>
T sum (T a, T b) {
  T result;
  result = (a+b);
  return (result);
}

and my overloaded + operator definition for class "Homework" looks like this:

//lhs.time + rhs.time = int result

int Homework::operator+ (const Homework rhs) const {
   
    int result;
    int a = this->time;
    int b = rhs.time;
    result  = (a+b);
    return result;
}

the + overload works fine when used like this:

int total = hw1 + hw2; 
cout << total << endl; 
// prints sum of hw1.time and hw2.time

... but fails to find the sum when I pass them off to the sum() template:

int total = sum<int> (hw, hw2);
cout << total << endl;
//yields an error!

the error yielded from g++ looks like this:
AddTwoObjects.cpp:69: error: no matching function for call to ‘sum(Homework&, Homework&)’

I've tried changing the template arguments to accept references but that breaks the template functionality for some reason. Can any one point out my mortal c++ sin?

Thanks

The templated sum() function tries to add a to b. Your + overload adds a.time to b.time. It should work if you call:

int total = sum<int> (hw.time, hw2.time);

David

time is private attribute of class Homework, and my sum() template function is used in the main() function, so objects cannot access those private vars outside the class declaration/definition... has to be something wrong with my template... obj.time is already accessed in my operator + overload definition.

int total = hw1 + hw2;

works though... just not with the template...

so... it doesn't work when I

int total = sum<int> (hw.time, hw2.time);

the error is with: AddTwoObjects.cpp:69: error: no matching function for call to ‘sum(Homework&, Homework&)’

I'm not sure what 'match' it's looking for...

Edited 6 Years Ago by brandonrunyon: n/a

The problem is that your + function returns an int. Your templated function was trying to return the same type as your inputs. So when you add a Homework to a Homework, it was trying to return a Homework, but your + function was returning an int, so it didn't make sense. Check out the working version below.

#include <iostream>
 
 class Homework
 {
   int time;
   
   public:
     void SetTime(int t){time = t;}
     int operator+ (const Homework rhs) const;
 };
 
template <class T>
int sum (T a, T b) {
  int result = a+b;
  return result;
}

//lhs.time + rhs.time = int result

int Homework::operator+ (const Homework rhs) const {
   
    int result;
    int a = this->time;
    int b = rhs.time;
    result  = (a+b);
    return result;
}

int main(int argc, char *argv[])
{
  Homework hw1;
  hw1.SetTime(1);
  
  Homework hw2;
  hw2.SetTime(2);
  
  {
  int total = hw1 + hw2; 
  std::cout << total << std::endl; 
  }
  
  int total = sum<Homework> (hw1, hw2);
  std::cout << total << std::endl; 

  return 0;
}

See what I mean?

David

If you want to keep the sum function template as is, you can also use the following code which uses the conversion operator (operator int()):

#include <iostream>
 
 class Homework
 {
   int time;
   
   public:
     void SetTime(int t) { time = t; }
     explicit Homework(int t) : time(t) { }; //add an explicit constructor with int.
     int operator int() const { return time; }; //add a conversion operator to int.
     int operator+ (const Homework& rhs) const;
 };
 
template <class T>
T sum (const T& a, const T& b) {
  T result = T(a+b); //make the result explicitly converted to T, in case the + operator does not already output a T object.
  return result;
}

//lhs.time + rhs.time = int result

int Homework::operator+ (const Homework& rhs) const {
    int a = this->time;
    int b = rhs.time;
    int result  = (a+b);
    return result;
}

int main(int argc, char *argv[])
{
  Homework hw1(1);
  
  Homework hw2(2);
  
  {
  int total = hw1 + hw2; 
  std::cout << total << std::endl; 
  }
  
  int total = sum(hw1, hw2); //no need for the explicit template argument here.
  std::cout << total << std::endl; 

  return 0;
}

This way, the sum function template could also be used for float or double, not just types that add up to an integer result.

Comments
awesome example! did not think to use conversions...

That template definition will implicitly cast any non int type (double, float,etc ...) to an int, defeating the purpose of my template to perform a sum on any type...

I tried overloading the function template with another declaration and def as you have it and it throws an error of "ambiguous" overload. Is there another way to do what I'm trying to do, perhaps overload in a "non-ambiguous" way?

You're right on otherwise. Thanks for that example. Very helpful otherwise.

Your + operator should return the same type as the inputs:

Homework Homework::operator+ (const Homework rhs) const {
   
    Homework result;
    int a = this->time;
    int b = rhs.time;
    result.SetTime(a+b);
    return result;
}
Comments
Thanks for your assistance, good clearity, sorry to make you repeat yourself :-\

@mike, Your implementation seems to fit my requirements nicely.

I'm getting an error using

int operator int() const { return time; };

Where keyword operator, int(), and const all have those squiggly red lines under them in my ide (netbeans).

I'm aware that they are all valid keywords when setting a user defined conversion. Am I missing something? I'm just testing the code you posted as is.
Thanks again for both of your inputs guys. :-)

I'm trying to test my sum() template function on ints, doubles, and Homework objects for an assignment. I've been able to get as far as writing the class, template function, and successfully passing ints and doubles to my template, but not the Homeworks... but I think you both have picked up on the gist of my requirements. Sorry if I wasn't totally explicit about that. Thanks again.

Edited 6 Years Ago by brandonrunyon: n/a

NVM Mike, I think I fixed that declaration by omitting the 'int' return type specifier.
Thanks!

You've both helped me get my head around my template and operator overload use and taught me a few things as well! Thanks! Case closed! :D

This question has already been answered. Start a new discussion instead.