Compiler variance in function template argument deduction

The following program:

#include <type_traits>

template<typename T, bool b>
struct S{
    S() = default;
    template<bool sfinae = true,
             typename = std::enable_if_t<sfinae && !std::is_const<T>::value>>
    operator S<T const, b>() { return S<T const, b>{}; }

template<typename T, bool x, bool y>
void f(S<const std::type_identity_t<T>, x>,
                                 // ^- T in non-deduced context for func-param #1 
       S<T, y>)
      // ^- T deduced from here

int main() {
    S<int, true> x{};
    S<int, false> y{};
    f(x, y);

is accepted by GCC (11.2) but rejected by Clang (13) and MSVC (19.latest), all for -std=c++20 / /std:c++20 (DEMO).

  • What compiler is correct here?

Source: Windows Questions C++