C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Add trait to get the type of a member function

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Fri, 28 Apr 2023 13:13:37 -0400
On Fri, Apr 28, 2023 at 12:33 PM Jason McKesson wrote:

> On Fri, Apr 28, 2023 at 10:55 AM Arthur O'Dwyer wrote:
> > On Fri, Apr 28, 2023 at 7:36 AM Anoop Rana wrote:
> >>
> >> Since the type of a non-static member function is an ordinary function
> type and since we can't use decltype on a non-static member function to get
> its type, I propose that we should add a trait to get back the type of a
> non-static member function.
> >
> > I don't understand what you mean. The type of a non-static member
> function is not an "ordinary function type" in the usual sense of the
> phrase; it's a member function type.
> > And `decltype` works just fine:
> >
> > // https://godbolt.org/z/Ea388neob
> > struct S {
> > int f() const;
> > };
> > static_assert(std::is_same_v<decltype(&S::f), int (S::*)() const>);
> >
> > Is it possible that you were actually trying to use `decltype(&S::g)` on
> an overload set?
> > https://godbolt.org/z/fj94db8cT
> >
> > [...]
> >>
> >> using ret1 = decltype(GetType(&C::Func))::type; // void(std::string,
> int) as expected
> >
> > But that's *not* what's expected! `C::Func` isn't a `void(std::string,
> int)` at all. It's a function of three parameters: the string, the int, and
> the hidden "this" parameter of type `C`. I cannot just pass a string and an
> int to it and have it work. It needs all three parameters in order to do
> its job.
>
> You may have missed the `GetType` metafunction there.
>

No, I saw it, but...

A deeper question is this: what exactly do you plan to *do* with this
> information?


...that's exactly what I meant. The type of `C::Func` is *not*
`void(std::string, int)`. You can't *do* anything with that information
alone; you need the `C::` part in order to actually call the member
function, or store a pointer to it somewhere, or pretty much anything else
you might want to *do* with it.

Anyway, if you [Anoop] just want a type transformation to add or remove
memberness, that's trivial to write. The only difficult part is coming up
with a name.
https://godbolt.org/z/PWsq3xshY

template<class F, class T> using add_member_pointer_t = F T::*;

template<class T> struct remove_member_pointer { using type = T; };
template<class T, class P> struct remove_member_pointer<P T::*> { using
type = P; };
template<class T> using remove_member_pointer_t = typename
remove_member_pointer<T>::type;

// ------

struct C {
void f(int, int) const;
void g(int);
};

static_assert(std::is_same_v<add_member_pointer_t<void(int, int) const, C>,
decltype(&C::f)>);
static_assert(std::is_same_v<add_member_pointer_t<void(int), C>, decltype
(&C::g)>);
static_assert(std::is_same_v<void(int, int) const, remove_member_pointer_t<
decltype(&C::f)>>);
static_assert(std::is_same_v<void(int), remove_member_pointer_t<decltype
(&C::g)>>);

–Arthur

Received on 2023-04-28 17:13:51