【发布时间】:2019-09-24 15:58:59
【问题描述】:
在查看工作中的一些代码时,我注意到一些我认为不应该编译的东西,但令我惊讶的是,它可以编译。
头文件中定义了一个模板函数:
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。在这种情况下,我相信它们会是一样的。
-
如果您从未在其他源文件中使用
utility::string_t版本,则不会违反 ODR,因为只有一个定义。 -
@RichardCritten 你有
has_field和has_string_field所以这些是不同的。 -
@Holt 好点
-
可以允许您跟进多个定义,您需要通过项目符号点:en.cppreference.com/w/cpp/language/definition
标签: c++ templates g++ one-definition-rule