How to define a template class template friend function which one of its parameters is a dependent name outside the template class body?

Viewed 47

Hello I have this program:

I want to create a generic class Add that works as a functor, I intend to overload the stream I/O operators to works with it.

The thing is that I want the stream operators << >> to be generic too, so that there stream parameter can be an std::istream or std::ifstream and so on. This applies to the insertion operator too.

The reason I do this is that if I write std::cout << Add<int>{} will prints it on the screen and if I do: ofstream("data.txt") >> Add<int>{}; will write it to the file.

  • I know an ifstream is an istream but I intend to use maybe other types that has their I/O operators doing another stuff.

      template <typename T>
      class Add
      {
          T operator()(T const& a, T const& b){return a + b;}
    
          template <typename STREAM_IN>
          friend STREAM_IN& operator >> (STREAM_IN& in, Add<T>& a){ in >> a.x; return in;}
    
          template <typename STREAM_OUT>
          friend STREAM_OUT& operator << (STREAM_OUT& out, Add<T> const& a){ out << a.x; return out;}
    
          int x = 89;
      };
    
      //template <typename T>
      //template <typename STREAM_IN>
      //STREAM_IN& operator >> (STREAM_IN& in, Add<T>& a)
      //{
      //    return in >> a.x;
      //}
    
    
      int main()
      {
    
          Add<long> a;
          std::ifstream in("data.txt");
          in >> a;
          std::cout << a << '\n';
          in.close();
          a.x += 7;
          std::ofstream out("data.txt");
          out << a;
    
    
          std::cout << "\ndone!\n";
      }
    
  • The problem: How can I defined >> and << outside the template class body?

1 Answers

Is this what you are looking for? I simply defined two overloaded operators using templates for both the stream and the template type of Add. Since Add is a struct and not a class you shouldn't need to use friend functions.

#include <iostream>
#include <fstream>
#include <string>

template <typename T>
class Add
{
    T operator()(T const& a, T const& b){return a + b;}

    template <typename STREAM, typename T2>
    friend STREAM& operator>>(STREAM& stream, Add<T2>& add);

    template <typename STREAM, typename T2>
    friend STREAM& operator<<(STREAM& stream, const Add<T2>& add);

    int x = 89;

public:
// in order to make the main function compile (not used by the operators)
    void add7() { x += 7; }
};

template <typename STREAM, typename T>
STREAM& operator>>(STREAM& stream, Add<T>& add) {
    stream >> add.x;
    return stream;
}

template <typename STREAM, typename T>
STREAM& operator<<(STREAM& stream, const Add<T>& add) {
    stream << add.x;
    return stream;
}

int main()
{

    Add<long> a;
    std::ifstream in("data.txt");
    in >> a;
    std::cout << a << '\n';
    in.close();
    a.add7();
    std::ofstream out("data.txt");
    out << a;


    std::cout << "\ndone!\n";
}

This part tells the compiler that this class is a friend to a function named operator>> that takes any type as first parameter and a class And`` of template type T```.

template <typename STREAM, typename T2>
friend STREAM& operator>>(STREAM& stream, Add<T2>& add);

And this part defines the body of the function.

template <typename STREAM, typename T>
STREAM& operator>>(STREAM& stream, Add<T>& add) {
    stream >> add.x;
    return stream;
}
Related