Ad

Equality Of Reference Types In Template Parameters

The C++ standard says in [temp.type]#2.7, that

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

This is different, than how reference types are compared in non-template code. Say e.g.

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

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

and

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

mean different things. equal_tmpl compares the addresses, but equal_fun compares the values:

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

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

Why is this defined this way in the standard? Souldn't equality in templates work the same way as in non-template code? Demo.

Ad

Answer

For the purposes of template argument equivalence, the question we want to be asking is "are these two arguments identical?" rather than "are these two arguments equal?"

References to two different variables that have the same value might be equal to each other, but they aren't identical: one may not be substituted for the other. Imagine if we had this:

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

Would it make any sense if the standard said that foo<i> and foo<j> are the same function because i == j (where i and j are defined as in the question)? No. foo<i> is a function that returns the address of i, and foo<j> is a function that returns the address of j, and those two addresses aren't the same.

Ad
source: stackoverflow.com
Ad