给定以下程序
#include <iostream>
template<class T> struct id { using type = T; };
template<class T1, class T2>
int func(T1, T2) { return 0; }
template<class T1, class T2>
int func(typename id<T1>::type, typename id<T2>::type) { return 1; }
int main()
{
std::cout << func<int, int>(0, 0) << std::endl;
}
GCC和Clang都打印此程序的1
。 此程序是否按标准保证打印1
?
我试图在这里找到答案,但无法破译。 看起来功能模板可能是等价的,因此打破了ODR,但我不确定。
将第二个函数模板更改为
template<class T>
using id_type = typename id<T>::type;
template<class T1, class T2>
int func(id_type<T1>, id_type<T2>) { return 1; }
有所作为?
我相信这是UB和违反ODR。 编译器不需要检查它,所以它可能会选择它喜欢的方式定义。 为什么相信这会破坏ODR? 主要是因为它的参数和返回类型被计算为相同的值。 这意味着它们在功能上是等价的,因为:
涉及模板参数的两个表达式如果不等价,则称为功能等价,但对于任何给定的模板参数集,对这两个表达式的求值结果都是相同的。
和功能等价的函数模板:
如果一个程序包含功能等价但不等价的函数模板的声明,则该程序是格式不良的; 不需要诊断。