【发布时间】:2016-02-06 00:41:06
【问题描述】:
以下是我在创建一个更大的类并尝试通过提供我自己的非成员朋友交换功能来实现 Swappable 时遇到的一个简化示例。
#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 类的模板交换函数没有正确实例化,尽管我在 main() 中使用了它?
【问题讨论】:
-
您需要先将
swap声明为模板,然后再将其声明为友元函数(template <typename T> void swap(Wrapper<T>&, Wrapper<T>&)。当然,这也意味着在 that 声明之前声明Wrapper,因为您将它们作为参数类型。
标签: c++ templates c++11 instantiation swap