Is this instance of stateful template metaprogramming well-defined?

Hol*_*Cat 6 c++

I'm learning stateful template metaprogramming.

I've stumbled upon this example, which I've slightly modified.

#include <iostream>

namespace impl
{
    template <typename T>
    struct tag
    {
        friend auto get(tag);
    };

    template <typename T, auto V>
    struct set
    {
        friend auto get(tag<int>) // <-- Originally it was `tag<T>`.
        {
            return V;
        }
    };
}

impl::set<int, 42> x;

int main()
{
    std::cout << get(impl::tag<int>{});
}
Run Code Online (Sandbox Code Playgroud)

For some reason, it works on GCC, but not on Clang.

I don't see anything wrong with the code, yet Clang complains about get not being defined:

error: function 'get' with deduced return type cannot be used before it is defined
Run Code Online (Sandbox Code Playgroud)

Interestingly, if I replace friend auto get(tag<int>) with friend auto get(tag<T>) it works on both compilers.

What's going on here? Is this example well-defined or not?


I tried simplyfing the example as much as possible, and arrived at this:

#include <iostream>

namespace impl
{
    struct tag {};

    auto get(tag);

    template <auto V>
    struct set
    {
        friend auto get(tag)
        {
            return V;
        }
    };
}

impl::set<42> x;

int main()
{
    std::cout << get(impl::tag{});
}
Run Code Online (Sandbox Code Playgroud)

This too only works on GCC.

Hol*_*Cat 1

从 Clang 12 开始,它可以在 Clang 中运行(感谢 @Fedor),所以这很可能是一个 Clang bug。