模板参数中引用类型的相等性

Equality of reference types in template parameters

C++ 标准在 [temp.type]#2.7 中说

Two values are template-argument-equivalent if they are of the same type and
...
(2.7) they are of reference type and they refer to the same object or function

这与在非模板代码中比较引用类型的方式不同。比如说

template <auto& x1, auto& x2>
constexpr bool equal_tmpl = false;

template <auto& x>
constexpr bool equal_tmpl<x, x> = true;

consteval bool equal_fun(auto& x1, auto& x2)
{
    return x1 == x2;
}

意思不同。 equal_tmpl 比较地址,但 equal_fun 比较值:

constexpr int i = 123;
constexpr int j = 123;

static_assert(equal_tmpl<i, j> != equal_fun(i, j));

为什么在标准中这样定义?难道模板中的相等性与非模板代码中的相等性不一样吗? Demo.

出于模板参数等价的目的,我们想问的问题是“这两个参数相同吗?”而不是“这两个参数 相等 吗?”

对具有相同值的两个不同变量的引用可能彼此相等,但它们并不完全相同:一个不能替代另一个。想象一下,如果我们有这个:

template <const int& r>
constexpr auto foo() { return &r; }

如果标准说 foo<i>foo<j> 是相同的函数,因为 i == j(其中 ij 是定义为问题)?不是,foo<i>是returns地址i的函数,foo<j>是returns地址j的函数,这两个地址不一样。