在审查工作中的一些代码时,我注意到一些我认为不应该编译的东西,但令我惊讶的是,它确实如此。
头文件中定义了一个模板函数:
template <class T>
web::json::value get_key(const web::json::value &json, const utility::string_t &key) {
return json.has_field(key) ? json.at(key) : web::json::value(T());
}
在源文件中具有专用性:
template <>
web::json::value get_key<utility::string_t>(const web::json::value &json, const utility::string_t &key) {
return json.has_string_field(key) ? json.at(key) : web::json::value(utility::string_t());
}
编辑:专用化未在头文件中声明。
据我所知,这应该导致编译器为get_key<utility::string_t>
发出两个不同的定义,一个用于源文件中的专用化,另一个用于主模板实例化,违反了 ODR。 但是,g++ 8.3.1 编译并链接它没有任何错误。
谁能解释一下这里发生了什么? 我是否遗漏了某些内容,并且上面的代码实际上是有效的,或者这只是一种未定义的行为?
谢谢!
没有违反 ODR。当需要专用化时,在首次使用函数模板之前,只应声明和显示专用化。