Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
200 views
Welcome To Ask or Share your Answers For Others

1 Answer

You need to say the following (since you befriend a whole template instead of just a specialization of it, in which case you would just need to add a <> after the operator<<):

template<typename T>
friend std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj);

Actually, there is no need to declare it as a friend unless it accesses private or protected members. Since you just get a warning, it appears your declaration of friendship is not a good idea. If you just want to declare a single specialization of it as a friend, you can do that like shown below, with a forward declaration of the template before your class, so that operator<< is regognized as a template.

// before class definition ...
template <class T>
class MyClass;

// note that this "T" is unrelated to the T of MyClass !
template<typename T>
std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj);

// in class definition ...
friend std::ostream& operator<< <>(std::ostream& out, const MyClass<T>& classObj);

Both the above and this way declare specializations of it as friends, but the first declares all specializations as friends, while the second only declares the specialization of operator<< as a friend whose T is equal to the T of the class granting friendship.

And in the other case, your declaration looks OK, but note that you cannot += a MyClass<T> to a MyClass<U> when T and U are different type with that declaration (unless you have an implicit conversion between those types). You can make your += a member template

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


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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...