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 to void()
. The way to spell that would be void(&)()
(which if you remove_reference_t
, you would get back void()
-- that is remove_reference_t
does 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:
struct C {
void f() &;
};
The type of &C::f
is void (C::*)() &
. But all pointers to members can be written as T C::*
for some type T
, and in this case the type T
would be void() &
.
See also P0172.
The type you have is not a reference to a function, but a function with a reference qualifier.
static_assert(std::is_same_v<void()&, void()&>);
static_assert(!std::is_same_v<void()&, void(&)()>);
static_assert(std::is_same_v<void(&)(), void(&)()>);
static_assert(std::is_same_v<void(), std::remove_reference_t<void(&)()>>);
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