未定义的对具有相同头文件中定义的模板运算符的引用

Undefined reference to template operator with definition in same header file

我在尝试使用我编写的模板化运算符时收到来自 clang++ 的链接器错误。

错误是:

main.cpp:(.text+0xfe): undefined reference to `operator<<(std::ostream&, schematic<130ul, 128ul, 130ul> const&)'
main.cpp:(.text+0x28c): undefined reference to `operator<<(std::ostream&, schematic<130ul, 1ul, 130ul> const&)'

现在,在我继续之前或者你将其标记为重复之前:我知道你不能将模板定义放在单独的 .cpp 文件中,而我没有这样做。 运算符的定义位于一个单独的头文件中,该头文件包含在其声明的头文件中,如 this answer 中所述。因为它仍然给我链接器错误,所以我在这里问。

代码

main.cpp

// includes

int main(int argc, char const* argv[])
{
    // ...

    switch (/* call */)
    {
        case /* one */:
            fout << mapArtFlat(/* ctor params */).exportScematic();
        break;
        case /* another */:
            fout << mapArtStaircase(/* ctor params */).exportSchematic();
        break;
    }
    return 0;
}

schematic.h

#ifndef SCHEMATIC_H
#define SCHEMATIC_H

// includes

template <std::size_t W, std::size_t H, std::size_t L>
class schematic
{
    friend std::ostream& operator<<(std::ostream&, const schematic<W,H,L>&);

    // class things
};

// output operator
template <std::size_t W, std::size_t H, std::size_t L>
std::ostream& operator<<(std::ostream&, const schematic<W,H,L>&);

// ...

#include "schematic_cpp.h"
#endif

schematic_cpp.h

// ...

// output operator
template <std::size_t W, std::size_t H, std::size_t L>
std::ostream& operator<<(std::ostream& lhs, const schematic<W,H,L>& rhs)
{
    // lot of code involving external libraries and processing data from the object
}

// ...

我尝试过的事情

您的示例大部分都有效,无法重现您遇到的错误。仍然发现应该更改的内容。

首先,您不能在尚未声明的函数上声明友谊。您需要将模板 operator<< 声明放在 class 定义之前。然而,当您尝试这样做时,您会意识到您需要声明原理图 class,因为它是函数类型的一部分。转发声明 class 你应该没问题:

template <std::size_t W, std::size_t H, std::size_t L>
class schematic;

template <std::size_t W, std::size_t H, std::size_t L>
std::ostream& operator<<(std::ostream&, const schematic<W,H,L>&);

template <std::size_t W, std::size_t H, std::size_t L>
class schematic {
    // ... stuff ...
};

其次,您需要明确声明您声明为友元的函数的模板参数(或者声明您与每个函数的每个模板参数都是友元)。您可以这样做:

template <std::size_t W, std::size_t H, std::size_t L>
class schematic
{
    friend std::ostream& operator<<<W,H,L>(std::ostream&, const schematic<W,H,L>&);
    // ... class stuff ...
};

如果解决这些不能解决您的问题,请尝试 post 完整 minimal reproducible example 您遇到的问题。您的链接问题可能与模板实例化因您在实施中所做的事情而被丢弃有关。