在模板类中声明的朋友模板函数导致未定义的符号链接错误

Mar*_*rco 5 c++ templates operator-overloading friend c++11

几天来,我一直在反对这一点,查找它并在开源项目中寻找类似的代码:无法真正找到我正在做错的事情.

基本上,考虑到下面的代码(提炼到其本质):

#include <iostream>


using std::cout;
using std::endl;
using std::string;

template <typename T>
class Node {
    T value_;
public:
    Node(const T& value) : value_(value) {}
    T const value() const { return value_; }

    friend
    std::ostream& operator <<(std::ostream& out, const Node<T>& node);

    Node<T> operator +(const Node<T>& other) {
        return Node(value() + other.value());
    }
};


template <typename T>
std::ostream& operator <<(std::ostream& out, const Node<T>& node) {
    return out << node.value();
}
Run Code Online (Sandbox Code Playgroud)

当在这样的代码中使用时:

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

    Node<string> node("node X");
    cout << node << endl;

    Node<int> three(3);
    cout << three << endl;

    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

我收到以下链接器错误:

Undefined symbols for architecture x86_64:
  "operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Node<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&)", referenced from:
      _main in StlPractice.cpp.o
  "operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Node<int> const&)", referenced from:
      _main in StlPractice.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)

据我所知,以上是所有合法的C++ 11代码; 模板是明确定义的,然而,它似乎以某种方式逃脱了链接器找到它的能力.

这是在OS X上使用cmake构建的:

cmake_minimum_required(VERSION 3.3)
project(simple_template)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(SOURCE_FILES src/simple_template.cpp)

add_executable(simple ${SOURCE_FILES})
Run Code Online (Sandbox Code Playgroud)

是什么赋予了?

提前致谢!

更新在问题之后,我还运行了以下相同的结果:

$ clang++ src/simple_template.cpp 
Undefined symbols for architecture x86_64:
  "operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Node<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&)", referenced from:
      _main in StlPractice-e20370.o
  "operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Node<int> const&)", referenced from:
      _main in StlPractice-e20370.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)

son*_*yao 7

作为朋友的类内部的声明是非模板函数,而类外的定义是模板函数,它们不匹配.对于重载分辨率,在模板函数专门化之前将选择非模板函数,这就是未定义符号链接错误发生的原因.

您可以将声明更改为模板函数:

template<typename X>
friend std::ostream& operator <<(std::ostream& out, const Node<X>& node);
Run Code Online (Sandbox Code Playgroud)

生活

或者在类中定义函数:

friend 
std::ostream& operator <<(std::ostream& out, const Node<T>& node) { return out << node.value(); }
Run Code Online (Sandbox Code Playgroud)

生活