[英]undefined reference to `operator<<(std::ostream&, /* class with non-type template parameters */&)'
For a homework assignment, I have to make a class with non-type template parameters and then add std::
( i
/ o
) stream
operators to it.对于家庭作业,我必须使用非类型模板参数制作 class ,然后添加
std::
( i
/ o
) stream
运算符。 However when I try to compile clang++ gives a linker error:但是,当我尝试编译 clang++ 时,会出现 linker 错误:
$ 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)
I am aware that template declarations and definitions have to be in the same translation unit, and there are plenty of questions & answers here that point that out.我知道模板声明和定义必须在同一个翻译单元中,这里有很多问题和答案都指出了这一点。
My abridged code is as follows:我的删节代码如下:
main.cpp:主.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:屏幕.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: 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
The operator<<
function declared inside the class is not a function-template, but later you are defining a function-template.在 class 中声明的
operator<<
function 不是函数模板,但稍后您将定义一个函数模板。 So you're declaring a different entity than what you are defining.因此,您声明的实体与您定义的实体不同。
You need to declare the function template inside the class as您需要在 class 中声明 function 模板为
template <std::size_t WX, std::size_t HX>
friend std::ostream& operator<<(std::ostream&, const Screen<WX, HX>&);
Note that the template parameters need to be named differently from the class template parameters, to avoid shadowing.请注意,模板参数的命名需要与 class 模板参数不同,以避免出现阴影。
You could also just define the operator<<
inside the class.您也可以在 class 中定义
operator<<
。
This friend operator这个朋友运营商
template <std::size_t W, std::size_t H>
class Screen
{
/////////////
// FRIENDS //
/////////////
friend std::ostream& operator<<(std::ostream&, const Screen<W,H>&);
//
is not a template operator.不是模板运算符。
So its definition as template operator is invalid.所以它作为模板运算符的定义是无效的。 That is it is not a definition of the non-template friend operator declared in the class definition.
也就是说,它不是 class 定义中声明的非模板友元运算符的定义。
As a result the compiler issues an error that the definition of the operator is not found.结果,编译器发出未找到运算符定义的错误。
Place the definition of the friend operator in the class definition.将友元运算符的定义放在 class 定义中。 In this case this definition will be used for each specialization of the class.
在这种情况下,此定义将用于 class 的每个特化。
Otherwise you will need to define the operator for each concrete specialization of the class separately.否则,您将需要分别为 class 的每个具体特化定义运算符。
Here is a demonstrative program.这是一个演示程序。
#include <iostream>
#include <iterator>
#include <numeric>
template <size_t N>
class Array
{
private:
int a[N];
public:
Array()
{
std::iota( std::begin( a ), std::end( a ), 0 );
}
friend std::ostream & operator <<( std::ostream &os, const Array &a )
{
for ( const auto &item : a.a ) os <<item << ' ';
return os;
}
};
int main()
{
std::cout << Array<1>() << '\n';
std::cout << Array<2>() << '\n';
std::cout << Array<3>() << '\n';
std::cout << Array<4>() << '\n';
std::cout << Array<5>() << '\n';
return 0;
}
Its output is它的 output 是
0
0 1
0 1 2
0 1 2 3
0 1 2 3 4
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.