c++templatesoperator-overloadingfriend

Operator overloading on class templates


I'm having some problems defining some operator overloads for template classes. Let's take this hypothetical class for example.

template <class T>
class MyClass {
  // ...
};

operator+=

// In MyClass.h
MyClass<T>& operator+=(const MyClass<T>& classObj);

// In MyClass.cpp
template <class T>
MyClass<T>& MyClass<T>::operator+=(const MyClass<T>& classObj) {
    // ...
    return *this;
}

Results in this compiler error:

no match for 'operator+=' in 'classObj2 += classObj1'

operator<<

// In MyClass.h
friend std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj);

// In MyClass.cpp
template <class T>
std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj) {
    // ...
    return out;
}

Results in this compiler warning:

friend declaration 'std::ostream& operator<<(std::ostream&, const MyClass<T>&)' declares a non-template function

What am I doing wrong here?


Solution

  • // In MyClass.h
    MyClass<T>& operator+=(const MyClass<T>& classObj);
    
    
    // In MyClass.cpp
    template <class T>
    MyClass<T>& MyClass<T>::operator+=(const MyClass<T>& classObj) {
      // ...
      return *this;
    }
    

    This is invalid for templates. The full source code of the operator must be in all translation units that it is used in. This typically means that the code is inline in the header.

    Edit: Technically, according to the Standard, it is possible to export templates, however very few compilers support it. In addition, you CAN also do the above if the template is explicitly instantiated in MyClass.cpp for all types that are T- but in reality, that normally defies the point of a template.

    More edit: I read through your code, and it needs some work, for example overloading operator[]. In addition, typically, I would make the dimensions part of the template parameters, allowing for the failure of + or += to be caught at compile-time, and allowing the type to be meaningfully stack allocated. Your exception class also needs to derive from std::exception. However, none of those involve compile-time errors, they're just not great code.