Класс шаблона не распознает дружественный оператор - PullRequest
0 голосов
/ 12 июля 2020

Итак, я пытаюсь включить два объявления друзей для оператора ввода и вывода в класс шаблона, но каждый раз, когда я компилирую код, кажется, что он не распознает оператор. вот мой файл заголовка.

ОШИБКА: Код серьезности Описание Ошибка состояния подавления строки файла проекта LNK2019 неразрешенный внешний символ "класс std :: basic_ostream & __cdecl operator << (класс std :: basic_ostream &, class Screen <5,5> &) "(?? 6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@AAV? $ Screen @ $ 04 $ 04 @@@ Z), на которое ссылается функция _main

Это похоже на ошибка связывания.

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

вот мой основной cpp файл

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 заметил, что проблему можно решить, включив объявление друга и определение функции в тело класса, но я не хочу расставлять точки таким образом.

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

Это меня смутило, и я пытаюсь понять, почему это работает именно так, а не наоборот, и я также заметил, что когда я включаю объявление друга, подобное этому

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

, кажется, что он работает, но он дает мне предупреждение, дающее мне знать, что определение функции для оператора не найдено, и это меня еще больше смутило. Эта проблема взята из п. п. С ++, глава 16, проблема 15

Ответы [ 2 ]

1 голос
/ 12 июля 2020
friend std::ostream& operator<< <> (std::ostream&, Screen&);
                                --

Без этих двух символов объявление друга объявляет не шаблон. То есть, когда вы создаете экземпляр Screen<3,5>, он попытается найти функцию с этой сигнатурой

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

, а не какой-либо шаблон функции. Такой функции нет, так что это не сработает. Объявление, которое работает, объявляет специализацию шаблона как друга, и шаблон существует и может быть создан, поэтому здесь нет проблем.

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

также работает точно так же. demo

Эти friend объявления требуют, чтобы объявление основного шаблона

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

находилось в области видимости (как в случае с вашим кодом).

0 голосов
/ 12 июля 2020

Друг внутри класса должен иметь полную специализацию:

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

Обратите внимание на <> после имени функции.

См. шаблон друзей .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...