当前位置: 首页 > 知识库问答 >
问题:

模板类无法识别友元运算符

阮俊弼
2023-03-14

因此,我试图在模板类中包含输入和输出运算符的两个友元声明,但每次编译代码时,它似乎都无法识别该运算符。这是我的头文件。

错误:严重性代码描述项目文件行抑制状态错误LNK2019未解析外部符号“class std::basic_ostream”

这似乎是一个链接错误。

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

我注意到这个问题可以通过在类体中包含友元声明和函数定义来解决,但是我不想这样做。

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&);

它似乎可以工作,但它给了我一个警告,让我知道我知道没有找到运算符的函数定义,这让我感到困惑,甚至more.This问题来自c Primer第5版第16章问题15

共有2个答案

鲁烨
2023-03-14

类内的朋友应该是完全特化的:

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

请注意

查看模板朋友。

丌官皓君
2023-03-14
friend std::ostream& operator<< <> (std::ostream&, Screen&);
                                --

如果没有这两个字符,友元声明将声明一个非模板。也就是说,当实例化< code>Screen时

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

而不是任何函数模板。没有这样的功能,所以这将失败。works 的声明将模板专用化声明为朋友,并且模板存在并且可以实例化,因此这里没有问题。

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

它也以完全相同的方式工作。演示

这些朋友声明要求主模板声明

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

在范围内(您的代码就是这种情况)。

 类似资料:
  • 我对这个错误有意见 错误LNK2019未解析的外部符号"类std::basic_ostream 现在,< code>post所做的就是调用< code >操作符 宣言 定义 它们分别位于文件和中,我要求运算符不是成员函数(用于赋值)。

  • 我想知道如果函数的模板参数包括但不限于类的模板参数,如何使函数成为类的朋友并在类外定义函数。 例如,我有以下模板类和模板朋友函数: 如果我编译: 我会得到以下链接器错误:

  • 我有一个类模板和一个函数模板定义了一个,它引用要绑定到的模板类型。 我想要的是将< code>make_obj函数声明为< code>friend,这样它可以创建< code>Obj的,但是其他人不能(除了通过copy ctor)。 我尝试了几个朋友声明,包括 和 后者是使< code>make_obj的所有模板实例化成为< code>Obj类的朋友的不太理想的尝试。然而,在这两种情况下,我得到相

  • 函数和整个类都可以声明为非模板类友元。使用类模板,可以声明各种各样的友元关系。友元可以在类模板与全局函数间、另一个类(可能是模板类)的成员函数间或整个类中(可能是模板类)建立。建立这种友元关系的符号可能很繁琐。 在下列X类的类模板中声明为: template<class T>class X 下列友元声明: friend void f1(); 使函数f1成为从上述类模板实例化的每个模板类的友元。 在

  • 来自Lippman et al C Primer第5版,第16.1.2节: 第一个问题:排队 为什么是<代码> 我添加了以下代码来定义运算符==并实例化类模板。它成功编译和链接: 如果我删除

  • 我使用JHipster以Gradle作为构建工具生成了应用程序。 当我创建实体时,我添加了过滤支持,这会生成JPA静态元模型。但是IntelliJ无法识别元模型。 我在IntelliJ上启用了注释处理器设置,但它似乎不起作用。 为了让IntelliJ识别JPA静态元模型,我必须更改哪些设置?