Для домашнего задания мне нужно создать класс с нетиповыми параметрами шаблона, а затем добавить к нему std::
(i
/ o
) stream
операторов. Однако, когда я пытаюсь скомпилировать, clang ++ выдает ошибку компоновщика:
$ clang++ -o foo ./*.cpp -std=c++11 -Wall -Wextra -Wpedantic -Wconversion -Wnon-virtual-dtor
/tmp/16_15-8cda65.o: In function `main':
main.cpp:(.text+0x108): undefined reference to `operator<<(std::ostream&, Screen<9ul, 9ul> const&)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Я осознаю, что объявления и определения шаблонов должны быть в одной и той же единице перевода, и здесь есть множество вопросов и ответов, которые указывают, что out.
Мой сокращенный код выглядит следующим образом:
main. cpp:
#include <iostream>
#include "Screen.h"
int main()
{
Screen<9,9> smile =
{
{0,0,0,1,1,1,0,0,0},
{0,1,1,0,0,0,1,1,0},
{0,1,0,0,0,0,0,1,0},
{1,0,0,1,0,1,0,0,1},
{1,0,0,0,0,0,0,0,1},
{1,0,1,0,0,0,1,0,1},
{0,1,0,1,1,1,0,1,0},
{0,1,1,0,0,0,1,1,0},
{0,0,0,1,1,1,0,0,0}
};
std::cout << smile;
return 0;
}
Screen.h:
#ifndef SCREEN_H
#define SCREEN_H
#include <iostream>
#include <array>
#include <initializer_list>
#include <cstddef>
template <std::size_t W, std::size_t H>
class Screen
{
/////////////
// FRIENDS //
/////////////
friend std::ostream& operator<<(std::ostream&, const Screen<W,H>&);
public:
// declarations of ctors, public members, etc.
private:
//////////
// DATA //
//////////
std::array<std::array<bool,W>,H> pixels;
};
/////////////////
// NON-MEMBERS //
/////////////////
// ostream operator
template <std::size_t W, std::size_t H>
std::ostream& operator<<(std::ostream&, const Screen<W,H>&);
#include "Screen_impl.h"
#endif
Screen_impl .h:
#ifndef SCREEN_IMPL_H
#define SCREEN_IMPL_H
#include <iostream>
#include <array>
#include <algorithm>
#include <stdexcept>
#include <initializer_list>
#include <cstddef>
// definitions...
/////////////////
// NON-MEMBERS //
/////////////////
// ostream operator
template <std::size_t W, std::size_t H>
std::ostream& operator<<(std::ostream& lhs, const Screen<W,H>& rhs)
{
for (auto y = rhs.pixels.cbegin(); y < rhs.pixels.cend(); ++y)
{
for (auto x = y->cbegin(); x < y->cend(); ++x)
{
if (*x)
lhs << '#';
else
lhs << ' ';
}
lhs << std::endl;
}
return lhs;
}
#endif