多翻译单元中模板仅实例化不同参数是否违反ODR?
关于函数模板
my_min是否违反ODR的合规性确认 三个翻译单元的代码
unit1.cpp
template <typename T> T my_min(T a, T b) { return my_less(a, b) ? a : b; } struct Test1 {}; inline bool my_less(Test1, Test1) { return true; } // 显式实例化,仅在本翻译单元 template Test1 my_min<Test1>(Test1, Test1);
unit2.cpp
template <typename T> T my_min(T a, T b) { return my_less(a, b) ? a : b; } struct Test2 {}; inline bool my_less(Test2, Test2) { return false; } // 显式实例化,仅在本翻译单元 template Test2 my_min<Test2>(Test2, Test2);
test.cpp及其他翻译单元
template <typename T> T my_min(T a, T b); // 本翻译单元无my_min<T>(T, T)的定义,只要其他翻译单元提供显式实例化即可 struct Test1 {}; struct Test2 {}; void test() { Test1 t1; Test2 t2; my_min(t1, t1); my_min(t2, t2); }
问题背景与标准依据
尽管my_min的定义在两个翻译单元中的标记序列完全一致,但它包含依赖表达式my_less(a, b)。
C++标准(当前草案)相关规定:
若模板D在多个翻译单元中定义,要求既适用于模板定义中使用的模板封闭作用域的名称,也适用于实例化点的依赖名称
其中一项要求是:在每个此类定义中,根据[basic.lookup]查找的对应名称,在重载解析和部分模板特化匹配后,应引用同一实体
显然,依赖名称my_less在实例化点查找时指向不同实体:my_less(Test1, Test1)和my_less(Test2, Test2),这是依赖名称的预期行为。
核心问题:这是否违反上述ODR要求(或其他要求)?
结论
这不构成ODR违反。类似场景在C++中非常常见:比如某个翻译单元定义了私有类及对应的swap()、begin()等函数,随后实例化标准算法时,算法会通过**依赖查找(ADL)**在实例化点找到这些与类绑定的函数。
具体到本例:
my_min<Test1>的显式实例化发生在unit1.cpp中,此时依赖查找my_less会找到unit1中定义的my_less(Test1, Test1),这是该实例化的正确关联实体;my_min<Test2>的显式实例化发生在unit2.cpp中,此时依赖查找my_less会找到unit2中定义的my_less(Test2, Test2),同样符合要求;- 两个显式实例化分别对应不同的模板特化,彼此独立,不存在ODR中要求的“同一实体需一致”的冲突——ODR针对的是同一模板特化在不同翻译单元中的定义一致性,而本例中不同特化的依赖查找结果不同是完全合法的。
内容的提问来源于stack exchange,提问作者Igor G
相关产品推荐
相关产品推荐

