模板函数定义未找到的问题
今天在写JSON解析器的时候发现的问题,代码如下。
JObject.h文件
Class JObject
{
public:
template <class T>
T &getValue(); //在类内声明了一个模板函数
};
JObject.cpp文件
#define THROW_GET_ERROR(errno) throw std::logic_error("type error in get " #errno " value!")
template <class T>
T &getValue()
{
// 添加安全检查
if constexpr (IS_SAMETYPE(T, t_str))
{
if (m_type != T_STR)
THROW_GET_ERROR(String);
}
else if constexpr (IS_SAMETYPE(T, t_bool))
{
if (m_type != T_BOOL)
THROW_GET_ERROR(Bool);
}
else if constexpr (IS_SAMETYPE(T, t_int))
{
if (m_type != T_INT)
THROW_GET_ERROR(Int);
}
else if constexpr (IS_SAMETYPE(T, t_double))
{
if (m_type != T_DOUBLE)
THROW_GET_ERROR(Double);
}
else if constexpr (IS_SAMETYPE(T, t_list))
{
if (m_type != T_LIST)
THROW_GET_ERROR(List);
}
else if constexpr (IS_SAMETYPE(T, t_dict))
{
if (m_type != T_DICT)
THROW_GET_ERROR(Dict);
}
void *v = getValuePtr();
if (v == nullptr)
throw std::logic_error("unknown type in JObject::Value()");
return *((T *)v);
}
编译的时候竟然出错
报错原因是找不到 getValue()模板函数的定义
问题解决
通常情况下,你会在.h文件中声明函数和类,而将它们的定义放置在一个单独的.cpp文件中。但是在使用模板时,这种习惯性做法将变得不再有用,因为当实例化一个模板时,编译器必须看到模板确切的定义,而不仅仅是它的声明。因此,最好的办法就是将模板的声明和定义都放置在同一个.h文件中。这就是为什么所有的STL头文件都包含模板定义的原因。------任何时候都适用的c++技巧-15
标准要求编译器在实例化模板时必须在上下文中可以查看到其定义实体;而反过来,在看到实例化模板之前,编译器对模板的定义体是不处理的——原因很简单,编译器怎么会预先知道typename 实参是什么呢?因此模板的实例化与定义体必须放到同一翻译单元中。
综上所述,只要将模板函数的声明和实现放在同一个文件中,一般是xxx.h文件中就可以正常编译!