Adding cv-qualifers to a typedef-ed function type

Viewed 43

In the following code, the last two static_asserts fail. But why? Where should I put the const to make the assertations pass?

#include <type_traits>

// these are ok
static_assert(!std::is_same_v<void(), const void()>);
static_assert(!std::is_same_v<void(), void() const>);
static_assert(!std::is_same_v<const void(), void() const>);
// so 'void()', 'const void()', 'void() const' are all distinct types

using F = void(); // or 'typedef void F()'; 

static_assert(std::is_same_v<const F, const void()>); // error!
static_assert(std::is_same_v<const F, void() const>); // error!

The above code may seem too abstract and like a pure language-lawyer code, so I'll explain in detail what led me to the question.

Real-life example

I had the following code:

#include <type_traits>

template <class>
struct X;

template <class T, class U>
struct X<T U::*> {
    using t = T;
};

struct A {
    void member() {}
};

static_assert(std::is_same_v<
    X<decltype(&A::member)::t, void()
>); // this is ok

My intention was that the X<pointer-to-member-function>::t would be the type of the written-outside-the-class version of the member-function (You probably know what I mean). And the code above runs fine, that is, the static_assert passes.

Next, I changed the definition of A to the following:

struct A {
    void const_member() const {}
};

and the static_assert to:

static_assert(std::is_same_v<
    X<decltype(&A::const_member)::t, void()
>);

Now the static_assert fails. But then I noticed that if I changed the void() in the static_assert to void() const it compiles. So I changed the partial speciailization of X to the following (so that X::t would be void())

template <class T, class U>
struct X<const T U::*> {
    using t = T;
};

but then, the compiler complains:

 error: incomplete type ‘X<void (A::*)() const>’ used in nested name specifier
   17 |             X<decltype(&A::const_member)>::t, void()

Apparently, the specialization is not selected.

0 Answers
Related