简体   繁体   English

未定义对 `operator<<(std::ostream&, /* class 与非类型模板参数 */&)' 的引用

[英]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.

相关问题 错误:“对运算符&lt;&lt;(std :: ostream&,Dogs const&)的未定义引用” - Error: “Undefined reference to operator<<(std::ostream&, Dogs const&)” std :: ostream&运算符&lt;&lt;类型推导 - std::ostream& operator<< type deduction “对&#39;std::operator&lt;&lt;(std::ostream&amp;, std::LinkedList const&amp;)的未定义引用”C++ - "Undefined reference to 'std::operator<<(std::ostream&, std::LinkedList const&)" C++ operator &lt;&lt;(ostream&os,...)用于模板类 - operator<<(ostream& os, …) for template class 包括“lvtocon.h”,对`operator&lt;&lt;(std::ostream&amp;, char const*)的未定义引用 - include "lvtocon.h", undefined reference to `operator<<(std::ostream&, char const*) 未定义对 `mtm::operator&lt;&lt;(std::ostream&amp;, mtm::DateWrap const&amp;)' 的引用 - undefined reference to `mtm::operator<<(std::ostream&, mtm::DateWrap const&)' 对`std :: ostream&SpyOutput :: operator &lt;&lt;的未定义引用 <double> (双const&)&#39; - undefined reference to `std::ostream& SpyOutput::operator<< <double>(double const&)' 非类型(引用)模板参数和链接 - Non-type (reference) template parameters and linkage 有关初始化类型为“ std :: ostream”的临时类的非常量引用“ std :: ostream&”的C ++编译器错误 - C++ compiler error regarding initialization of a non-const reference of type 'std::ostream&' from a temporary of type 'std::ostream" 重载&lt;&lt;在C ++中的运算符-为什么返回类型是引用std :: ostream& - Overloading the << operator in C++ -why return type is a reference std::ostream&
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM