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.
It works in Clang starting with Clang 12 (thanks @Fedor), so this was most probably a Clang bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With