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

Categories

0 votes
218 views
in Technique[技术] by (71.8m points)

c++ - 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?

See Question&Answers more detail:os

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

1 Answer

0 votes
by (71.8m points)

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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...