I have a class of shapes, it works on the principle that a shape consists of points (x and y coordinates). But overloading the input and output operators I encountered a problem that could serve as an error.
This is what the compiler says:
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;
}
The declaration
is not a template declaration. But
is a template.
You need to declare the functions as templates from the start:
Also please read Why can templates only be implemented in the header file?
Templates can't really be split into separate source and header files like that.