Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this instance of stateful template metaprogramming well-defined?

Tags:

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>{});
}

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

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{});
}

This too only works on GCC.

like image 606
HolyBlackCat Avatar asked Nov 19 '19 16:11

HolyBlackCat


1 Answers

It works in Clang starting with Clang 12 (thanks @Fedor), so this was most probably a Clang bug.

like image 124
HolyBlackCat Avatar answered Nov 13 '22 08:11

HolyBlackCat