1

I confronted different issues when overloading the addition operator of a template class.

I finally found a solution and the codes below can work without any issue.

template<class T>
class A;

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

template <class T>
A<T> operator+ (A<T> & a1, A<T> & a2){
    //the definition of the function
}

template <class T>
class A{
    friend A<T> operator +<> (const A<T>& , const A<T>& );
    private: //...whatever
    public: //...whatever
};

However, after I did some experiment with the codes above, I'm very confused.

  1. I change the friend function declaration in class A
    from friend A<T> operator +<> (const A<T>& , const A<T>& );
    to friend A<T> operator + (const A<T>& , const A<T>& );
    (the <> after the operator + is deleted)
    Then the codes can run and give a result, but I get a warning: warning: friend declaration 'A<T> operator+(const A<T>&, const A<T>&)' declares a non-template function

  2. Without making the modification in step 1, I delete the template declaration of the addition operator overloading function. So the code below is deleted:

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

    Then I got an error:error: template-id 'operator+<>' for 'A<int> operator+(const A<int>&, const A<int>&)' does not match any template declaration

  3. I make both modifications in step 1 and step 2, then get the same warning in step 1:warning: friend declaration 'A<T> operator+(const A<T>&, const A<T>&)' declares a non-template function


I'm confused by the issues caused by those modifications.

  1. What's the effect of the <> after operator +? (see the first modification)
  2. What's the effect of deleting the template declaration of the addition operator overloading function? (see the second modification)
  3. Why the code can't run and returns an error when I only make the second modification, while it can run and returns a warning when I make both the first and second modification?

Thanks in advance!

llxxee
  • 59
  • 1
  • 6

1 Answers1

1

Case 1: friend A<T> operator +<> (const A<T>& , const A<T>& ) is actually a friend specialization of following function for type T (which is class template's type).

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

If you want to specialize this function for a specific type like int you do like this:

template<>
A<int> operator+(const A<int>&, const A<int>&)
{
}

So your friend function is a specialized friend function.

when you remove <> your friend function turn into a normal friend function but your actual operator+ is a template function. compiler is warning you because your class definition has a non-template declaration of the friend function (without the template), but the friend function definition is a function template. Change your friend function to the following to suppress warning.

template<class T1>
friend A<T1> operator+ (const A<T1>&, const A<T1>&);

Case 2: You get that error because your deceleration and definition of operator + differ in const qualifier for parameters. Actually they are completely two different function that second function isn't definition of the first one. Add const to the parameters of your function definition.

Indeed when you remove this code:

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

Compiler can't found a template function for your friend deceleration that take two const A<T>& parameter.

MRB
  • 3,752
  • 4
  • 30
  • 44
  • Thanks! I added `const` in the definition of `operator +` and it worked well. But the first code fragment (without modification 1 or 2) in my question still has no `const` in its `operator +` definition, while having `const` in its declaration. Why can it run without issue? – llxxee Jan 16 '17 at 16:02
  • @llxxee You are declaring two different function that differ in `const`ness of their parameters. one of them is friend of your class and has no definition and another has definition but because it's signature differ from friend function deceleration, it wont be friend with your class. Compiler doesn't complain because first function never call. if you add two `const A` you will get `unresolved external` linker error or if you access to private member variable of `A` inside `operator+` you will see that compiler complain `can't access to private member of A`. – MRB Jan 16 '17 at 16:12
  • @llxxee Sorry for my bad English. Sometimes I have a sentence in my head but I can't express it in English very well. – MRB Jan 16 '17 at 16:29
  • 1
    Your explanation is very clear for me : ) By the way, I found that if I declare a function like `void f(const int m)` and define it without `const` like `void f(int m) {cout< – llxxee Jan 16 '17 at 16:45
  • @llxxee Your example is just a special case. For more info for this case see here: http://stackoverflow.com/q/117293/2279977 But you can change your parameter to int& and call your function with a `const` variable. (`const int i = 5; f(i);`) You will see that you will get `unresolved symbol` error. – MRB Jan 16 '17 at 16:59