C++20: Concepts of multiple types and its constraint, correct syntax?

You can write it like this:

template <typename T1, typename T2>
    requires AreEqComparable<T1, T2>
bool are_equal(T1 a, T2 b)
{
    // ...
}

Here, we use a requires-clause to impose a requirement on the type template parameters.


You can write:

template <typename T1, AreEqComparable<T1> T2>
bool are_equal(T1, T2);

This is equivalent to:

template <typename T1, typename T2>
    requires AreEqComparable<T2, T1>
bool are_equal(T1, T2);

The types are flipped in the constraint here, AreEqComparable<T2, T1> instead of AreEqComparable<T1, T2>. This will certainly matter for many concepts, but probably not this one in particular since == itself becomes symmetric in C++20 (short of pathological cases which should not exist in real code). And if you want to be really sure that this symmetry is valid, you can always make it explicit in the concept (as EqualityComparableWith is in the working draft):

template<typename T1, typename T2>
concept AreEqComparable = requires(T1 a, T2 b) {
    { a == b } -> bool;
    { b == a } -> bool;
};

You can actually get the constraint you want in the correct order by flipping the order of the template parameters (h/t Matthieu M.):

template <typename T2, AreEqComparable<T2> T1>
bool are_equal(T1, T2);

Yet another syntax that avoids introducing template parameters at all (at the cost of adding other redundancy):

bool are_equal(auto x,auto y)
  requires AreEqComparable<decltype(x),decltype(y)>
  {return x==y;}