用户定义 class 的交换函数从未实例化?

Swap function for user-defined class never instantiated?

以下是我遇到更大的问题的简化示例 class 我正在创建并尝试通过提供我自己的非会员朋友交换功能来实现可交换。

#include <iostream>
#include <utility>

template<typename T>
class Wrapper {
  friend void swap(Wrapper& a, Wrapper& b);

public:
  Wrapper(T t) : value_(t) {}
  const T& operator*() const { return value_; }

private:
  T value_;
};

template<typename T>
void swap(Wrapper<T>& a, Wrapper<T>& b) {
  using std::swap;
  swap(a.value_, b.value_);
}

int main() {
  Wrapper<int> w1{5}, w2{10};
  std::cout << *w1 << " " << *w2 << std::endl;
  swap(w1, w2);
  std::cout << *w1 << " " << *w2 << std::endl;
}

尝试编译这个小测试程序会导致来自 clang 的以下链接器错误(Apple LLVM 版本 7.0.2,OS X El Capitan 10.11.3 上的 clang-700.1.81):

[~/Development/c++_test][16:30:57]$ clang++ --std=c++11 -o SwapTest SwapTest.cc
Undefined symbols for architecture x86_64:
  "swap(Wrapper<int>&, Wrapper<int>&)", referenced from:
      _main in SwapTest-a978ea.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

为什么我定义的 Wrapper class 的模板交换函数没有正确实例化,尽管我在 main() 中使用了它?

friend void swap(Wrapper& a, Wrapper& b);

声明一个非模板函数 swap,它恰好接受 Wrapper<T>& 个参数。这与您的模板函数 swap<T>.

不匹配

一个简单的修复方法是将 friend 声明为模板函数。

template <typename U>
friend void swap(Wrapper<U>&a, Wrapper<U>& b);

缺点是你的朋友比你想要的多一点:每个 swap 实例都是每个 Wrapper<T> 的朋友,而不仅仅是正确的 Wrapper<T> class.

更正确的方法是在 class:

之前声明模板函数
template <class T> class Wrapper;
template <class T>
void swap(Wrapper<T>&, Wrapper<T>&);

template <class T>
class Wrapper
{
    friend void swap<>(Wrapper&, Wrapper&);
    // ...

只需将您的好友声明更改为模板即可:

template<typename T>
class Wrapper {
  template<typename U>
  friend void swap(Wrapper<U>& a, Wrapper<U>& b);
  ...

gcc 在尝试编译您的代码时输出有关此的警告