关于模板函数只能在头文件中实现这件事
最近在实现一个序列化功能,大致如下:
// seialize.h
#pragma once
#include <vector>
#include <type_traits>
class Serializer
{
public:
template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
bool serialize(const T &data);
private:
std::vector<char> _buffer;
};
// serialize.cc
#include "traits.h"
#include <iostream>
template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
bool Serializer::serialize(const T &data)
{
std::cout << "serialize is_floating_point..." << std::endl;
return false;
}
// main.cc
#include "traits.h"
#include <iostream>
int main()
{
Serializer s;
float f;
s.serialize(f);
double d;
s.serialize(d);
return 0;
}
然后,编译,报错:
g++ -std=c++11 main.cc serialize.cc
/tmp/cc6mdxGl.o: In function `main':
main.cc:(.text+0x33): undefined reference to `bool Serializer::serialize<float, float>(float const&)'
main.cc:(.text+0x46): undefined reference to `bool Serializer::serialize<double, double>(double const&)'
collect2: error: ld returned 1 exit status
嗯,链接失败。但是,如果我们将serialize.cc
中的实现放到serialize.h
中,则可以编译通过,正常调用。为什么呢?这涉及到一个广为人知
的规则——模板函数只能在头文件中实现
。下面这篇文章从编译的角度解释原因——关于模板类的函数定义只能写在头文件这事