问题在于使用模板编写运算符重载<< and >>

问题描述 投票:0回答:3
我有一类形状,它的工作原理是形状由点(x 和 y 坐标)组成。但是,在重载输入和输出运算符时,我遇到了一个可能会导致错误的问题。

编译器是这么说的:

In file included from main.cpp:1: ./header/figure.h:17:82: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const Figure<T>&)’ declares a non-template function [-Wnon-template-friend] 17 | friend std::ostream & operator<<(std::ostream & stream, const Figure<T> & fig); | ^ ./header/figure.h:17:82: note: (if this is not what you intended, make sure the function template has already been declared and add ‘<>’ after the function name here) ./header/figure.h:18:76: warning: friend declaration ‘std::istream& operator>>(std::istream&, Figure<T>&)’ declares a non-template function [-Wnon-template-friend] 18 | friend std::istream & operator>>(std::istream & stream, Figure<T> & fig); | ^ /usr/bin/ld: /tmp/ccVeFfI2.o: в функции «main»: main.cpp:(.text+0xdb): неопределённая ссылка на «operator<<(std::ostream&, Figure<double> const&)» /usr/bin/ld: main.cpp:(.text+0xf1): неопределённая ссылка на «operator>>(std::istream&, Figure<double>&)» collect2: error: ld returned 1 exit status

figure.h


#pragma once #include <ostream> #include "./dynamicArray.h" template <class T> class Figure { public: Figure(); Figure(const DArray<std::pair<T, T>> & points); Figure(const std::initializer_list<std::pair<T, T>> & coord); ~Figure() noexcept; friend std::ostream & operator<<(std::ostream & stream, const Figure<T> & fig); friend std::istream & operator>>(std::istream & stream, Figure<T> & fig); protected: DArray<std::pair<T, T>> _points; std::string _name = "unnamed"; }; #include "../src/figure.cpp"

figure.cpp


#include "../header/figure.h" template <class T> Figure<T>::Figure() : _points() {} template <class T> Figure<T>::Figure(const DArray<std::pair<T, T>> & points) : _points(points) {} template <class T> Figure<T>::Figure(const std::initializer_list<std::pair<T, T>> & coord) : _points(coord) {} template <class T> Figure<T>::~Figure() noexcept { } template <class T> std::ostream & operator<<(std::ostream & stream, const Figure<T> & fig) { size_t size = fig._points.getSize(); if (size == 0) { return stream << 0; } for (size_t i = 0; i < size; ++i) { stream << "Point " << i + 1 << "| "; stream << fig._points[i]; } return stream; } template <class T> std::istream & operator>>(std::istream & stream, Figure<T> & fig) { std::pair<T, T> tmp; std::cout << "Enter Ox: "; stream >> tmp.first; std::cout << "Enter Ox: "; stream >> tmp.second; fig._points.pushBack(tmp); return stream; }
    
c++ templates operator-overloading ostream istream
3个回答
0
投票
声明

friend std::ostream & operator<<(std::ostream & stream, const Figure<T> & fig);

不是模板声明。但是

template <class T> std::ostream & operator<<(std::ostream & stream, const Figure<T> & fig)

一个模板。

您需要从一开始就将函数声明为模板:

template<typename U> friend std::ostream & operator<<(std::ostream & stream, const Figure<U> & fig);


另请阅读

为什么模板只能在头文件中实现?

模板不能真正拆分为单独的源文件和头文件。


0
投票
问题是

friend declaration ‘std::ostream& operator<<(std::ostream&, const Figure<T>&)’ declares a non-template function

,但是后来你把它定义为模板函数。解决方案是首先将其声明为模板函数。

template <class T> friend std::ostream & operator<<(std::ostream & stream, const Figure<T> & fig); template <class T> friend std::istream & operator>>(std::istream & stream, Figure<T> & fig);
对于这些重载,声明 

Figure<T>

every T
 交友感觉有点奇怪,但这是简单的解决方案。

“更正确”的解决方案稍微棘手一些。语法超出了我的想象,可能有点错误,但应该是这样的

//declare the class as existing as a template type. template <class T> class Figure; //declare the function as existing as a template function. template <class T> std::ostream & operator<<(std::ostream & stream, const Figure<T> & fig); //define the class template<class T> class Figure { public: .... //now you can friend the specific instantiations friend std::ostream & operator<<(std::ostream & stream, const Figure<T> & fig); friend std::istream & operator>>(std::istream & stream, Figure<T> & fig);
或者语法可能是 

friend std::ostream & operator<< <T>(std::ostream & stream, const Figure<T> & fig)

 之类的。我不确定。


0
投票
最简单的方法是内联友元函数。我们可以组合的另一件事是

模板名称注入;即在模板内部,您不需要模板参数列表,除非您引用具有不同参数集的另一个实例化:

template<typename T> struct test{ T val; friend auto& operator << (std::ostream& os, test const& x){ return os << "value=" << x.val << "\n"; }; }; std::cout << test<int>{1} << test<std::string>{"hello"};
您可以从这个简单的示例开始,并对其进行详细说明以获得最终结果。

© www.soinside.com 2019 - 2024. All rights reserved.