Ran into something strange when doing some template metaprogramming the other day. It basically comes down to this assertion not (as I would expect) passing.
static_assert(std::is_same_v<void(), std::remove_reference_t<void()&>>);
At first I thought I was making a syntactic mistake defining a function reference, but this assertion passes, showing that's not the case.
static_assert(std::is_same_v<void()&, void()&>);
I also tried implementing remove_reference myself copying the source from cppreference but that didn't work either. What is going on here?
Welcome to the world of Abominable Function Types.
void() &is not a reference tovoid(). The way to spell that would bevoid(&)()(which if youremove_reference_t, you would get backvoid()-- that isremove_reference_tdoes work on references to functions, if what you provide it is actually a reference to function type).What
void() &actually refers to is the type of a reference-qualified member function after you strip off the class. That is:The type of
&C::fisvoid (C::*)() &. But all pointers to members can be written asT C::*for some typeT, and in this case the typeTwould bevoid() &.See also P0172.