I'm experimenting with deducing this
in order to simplify a code base. I'm getting an issue with a straightforward test:
#include <iostream>
#include <type_traits>
#include <utility>
class S {
public:
auto Get(this auto&& self) -> auto&& {
return std::forward_like<decltype(self)>(self.val);
}
private:
int val{0};
};
int main() {
S const s;
std::cout << std::is_rvalue_reference_v<decltype(s.Get())> << '\n';
std::cout << std::is_const_v<
std::remove_reference_t<decltype(s.Get())>> << '\n';
std::cout
<< std::is_rvalue_reference_v<decltype(std::move(s).Get())> << '\n';
std::cout
<< std::is_const_v<
std::remove_reference_t<decltype(std::move(s).Get())>> << '\n';
}
msvc and gcc are giving the expected result, but not clang, that gives:
error: function 'forward_like<const S &, const int &>' with deduced return type cannot be used before it is defined
note: in instantiation of function template specialization 'S::Get<const S &>' requested here
std::cout << std::is_rvalue_reference_v<decltype(s.Get())> << '\n';
and
error: no matching member function for call to 'Get'
std::remove_reference_t<decltype(s.Get())>> << '\n';
~~^~~
note: candidate template ignored: substitution failure [with self:auto = const S &]
auto Get(this auto&& self) -> auto&& {
Plus other similar errors on next lines.
What's the issue?
This is a bug in clang in the std::forward_like
implementation:
clang 16 -> 17 regression: "deduced return type cannot be used before it is defined"
The workaround is to use -fno-builtin-std-forward_like
when compiling.
godbolt example
Or use clang trunk, which already contains the fix:
godbolt example