Search code examples
c++friendostream

unable to access friend function in template class


The Pairwise class represents a pair with a key:value. I've made a template pair and was having errors trying to run with a key and value input to the class and printing it out.

Given my main:

#include "file_name.h"

int main (){
    Pairwise<string, string> example = {{"key", "value"}};
    cout << example << endl;
 }

And my header file:

#pragma once

#include<iostream>
using std::ostream; using std::cout; using std::endl;
#include<string>
using std::string;
#include<utility>
using std::pair;
#include<sstream>
using std::ostringstream;

template<typename K, typename V>
struct Pairwise{
    K first;
    V second;
    Pairwise() = default;
    Pairwise(K, V);
    //print out as a string in main
    friend ostream& operator<<(ostream &out, const Pairwise &n) {
        ostream oss;
        string s;
        oss << n.first + ":" + n.second; //possible error?
        s = oss.str();
        out << s; 
        return out;
    }
};

My expected output after running main would be:

key:value

However, I am getting the error:

h:28:11: error: 'std::basic_ostream<_CharT, _Traits> is protected within..."

Solution

  • h:25:59: friend declaration delares a non template function.

    You are missing to declare the function as a template that takes Pairwise<K, V>:

    header.h:

    #ifndef HEADER_H_INCLUDED  /* or pragma once */
    #define HEADER_H_INCLUDED  /* if you like it */
    
    #include <iostream>  // or <ostream>
    
    template<typename K, typename V>
    class Pairwise {  // made it a class so that the
        K first;      // friend actually makes sense.
        V second;
    
    public:
        Pairwise() = default;
    
        Pairwise(K first, V second)
        : first{ first }, second{ second }
        {}
    
        template<typename K, typename V>
        friend std::ostream& operator<<(std::ostream &out, Pairwise<K, V> const &p)
        {
            return out << p.first << ": " << p.second;
        }
    };
    
    #endif /* HEADER_H_INCLUDED */
    

    source file:

    #include <iostream>  // the user can't know a random header includes it
    #include <string>
    
    #include "header.h"
    
    int main()
    {
        Pairwise<std::string, std::string> p{ "foo", "bar" };
        std::cout << p << '\n';
    }
    

    Sidenote: You could also use

    {
        using Stringpair = Pairwise<std::string, std::string>;
        // ...
        Stringpair sp{ "foo", "bar" };
    }
    

    if you need that more often.

    The other errors you got result from confusing std::ostringstream with std::ostream in operator<<().