简体   繁体   中英

Template class not recognizing friend operator

So I'm trying to include two friend declarations for the input and output operator in a template class but every time I compile the code it doesn't seem to recognize the operator. here is my header file.

ERROR:Severity Code Description Project File Line Suppression State Error LNK2019 unresolved external symbol "class std::basic_ostream<char,struct std::char_traits > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits > &,class Screen<5,5> &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@AAV?$Screen@$04$04@@@Z) referenced in function _main

It seems to be a linking error.

Screen.h

#include<string>
#include<iostream>
template<std::string::size_type, std::string::size_type>
class Screen;

template<std::string::size_type w, std::string::size_type h>
std::ostream& operator<<(std::ostream&,Screen<w, h>&);


template<std::string::size_type w,std::string::size_type h> 
class Screen{

    friend std::ostream& operator<<(std::ostream&, Screen&);
public:
    Screen()=default;
    Screen(const char str=' '):content(w*h,str){}

    Screen& set(char);
    Screen& set(std::string::size_type,std::string::size_type,char);
    char get() const {return content[cursor];}
    inline char get(std::string::size_type,std::string::size_type)const;

    Screen& move(std::string::size_type,std::string::size_type);
    Screen& display(std::ostream& os) { os<<content;  return *this; }



private:
    //void do_display(std::ostream& os) const { os << content; }
    std::string::size_type cursor=0;
    std::string content;
};
//MEMBER FUNCTIONS
template<std::string::size_type w,std::string::size_type h>
inline Screen<w,h>& Screen<w,h>::set(char c){
    content[cursor] =c;
    return *this;
}

template<std::string::size_type w,std::string::size_type h>
inline Screen<w,h>& Screen<w,h>::set(std::string::size_type r,std::string::size_type col,char ch){
    content[r*w+col]=ch;
    return *this;
}

template<std::string::size_type w,std::string::size_type h>
 inline Screen<w,h>& Screen<w,h>::move(std::string::size_type r,std::string::size_type c){
    cursor = r + w + c;
    return *this;
}

template<std::string::size_type w,std::string::size_type h>
inline char Screen<w,h>::get(std::string::size_type r,std::string::size_type c)const{
    return content[r*w+c];
}

//OS OPERATOR

template<std::string::size_type w, std::string::size_type h>
std::ostream& operator<<(std::ostream& os, Screen<w, h>& item) {
    os << item.content;
    return os;
}

here is my main cpp file

main.cpp

#include"Screen.h"
#include<string>
#include<iostream>

using std::cout; using std::endl;
using std::string;

int main(){
    Screen<5,5> myScreen('X');
    myScreen.move(4, 0).set('#').display(cout);
    cout << endl;
    myScreen.display(cout);
    cout << endl;
    cout << myScreen << endl;
}

I noticed that the problem could be fixed by including the friend declaration and the function definition inside the class body but I don't want to dot it this way.

public:
... other code

template<std::string::size_type w, std::string::size_type h>
friend std::ostream& operator<<(std::ostream& os, Screen<w, h>& item) {
    os << item.content;
    return os;
}

This confused me and I'm trying to understand why it works this way but not the other way, and I also noticed that when I include the friend declaration like this

    friend std::ostream& operator<<<w,h>(std::ostream&, Screen&);

it seems to work but it gives me a warning letting know me know that the function definition for the operator is not found, and that confused me even more.This problem is from c++ primer 5th edition chapter 16 problem 15

friend std::ostream& operator<< <> (std::ostream&, Screen&);
                                --

Without these two characters, the friend declaration declares a non-template. That is, when you instantiate Screen<3,5> , it will attempt to find a function with this signature

std::ostream& operator<< (std::ostream&, Screen<3,5>&);

and not any function template. There is no such function so this will fail. The declaration that works declares a template specialisation as a friend, and the template exists and can be instantiated, so no problem here.

friend std::ostream& operator<< <w, h> (std::ostream&, Screen&);

also works exactly the same way. demo

These friend declarations require that the main template declaration

template<std::string::size_type w, std::string::size_type h>
std::ostream& operator<<(std::ostream&,Screen<w, h>&);

is in scope (which is the case with your code).

The friend inside the class should be a full specialization:

friend std::ostream& operator<< <>(std::ostream&, Screen&);

Note the <> after the function name.

See template friends .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM