Can I get the Owning Object of a Member Function Template Parameter?

喜欢而已 提交于 2019-12-18 19:09:16

问题


Given a object:

struct foo {
    void func();
};

Now given the templatized function declaration:

template<typename T, T F>
void bar();

So bar will be taking in a member function like so:

bar<decltype(&foo::func), &foo::func>()

In the body of bar I want to recover the type foo from T. Can I do that? I want to be able to do something like this:

get_obj<T> myfoo;

(myfoo.*F)();

I know that get_obj isn't a thing, but would there be a way to write it?


回答1:


template<class T>
struct get_memfun_class;
template<class R, class T, class...Args>
struct get_memfun_class<R(T::*)(Args...)> {
  using type=T;
};
template<class T>
using get_memfun_class_t=typename get_memfun_class<T>::type;


template<auto M>
using class_of_memfun = get_memfun_class_t< decltype(M) >;

class_of_memfun<F> is then the class of the memberfunction F.

To handle const/volatile/etc you end up having to do a bunch of versions. This is annoying. Here is an example of it:

template<class T>
struct get_memfun_class;
#define GET_MEMFUN_CLASS(...) \
template<class R, class T, class...Args> \
struct get_memfun_class<R(T::*)(Args...) __VA_ARGS__> { \
  using type=T; \
}

possibly you want:

template<class R, class T, class...Args> \
struct get_memfun_class<R(T::*)(Args...) __VA_ARGS__> { \
  using type=T __VA_ARGS__; \
}

is the type of the class of a pointer to a const memfun a const class or not?

Once you have chosen, you need to write 24 uses of the above macro:

GET_MEMFUN_CLASS();
GET_MEMFUN_CLASS(const);
GET_MEMFUN_CLASS(volatile);
GET_MEMFUN_CLASS(const volatile);
GET_MEMFUN_CLASS(&);
GET_MEMFUN_CLASS(const&);
GET_MEMFUN_CLASS(volatile&);
GET_MEMFUN_CLASS(const volatile&);
GET_MEMFUN_CLASS(&&);
GET_MEMFUN_CLASS(const&&);
GET_MEMFUN_CLASS(volatile&&);
GET_MEMFUN_CLASS(const volatile&&);
GET_MEMFUN_CLASS(noexcept);
GET_MEMFUN_CLASS(const noexcept);
GET_MEMFUN_CLASS(volatile noexcept);
GET_MEMFUN_CLASS(const volatile noexcept);
GET_MEMFUN_CLASS(& noexcept);
GET_MEMFUN_CLASS(const& noexcept);
GET_MEMFUN_CLASS(volatile& noexcept);
GET_MEMFUN_CLASS(const volatile& noexcept);
GET_MEMFUN_CLASS(&& noexcept);
GET_MEMFUN_CLASS(const&& noexcept);
GET_MEMFUN_CLASS(volatile&& noexcept);
GET_MEMFUN_CLASS(const volatile&& noexcept);
#undef GET_MEMFUN_CLASS

template<class T>
using get_memfun_class_t=typename get_memfun_class<T>::type;

I am unaware of a way to avoid doing all 24 of these specializations for full coverage. If you think this is dumb, you are right; please feel free to express your annoyance by proposing a fix to the C++ standard committee.

If you are doing something like this for more than one trait, you can write the "strip lvalue, rvalue, noexcept and cv qualifiers" off part at one spot and pass them down in pieces.

Live example.




回答2:


If you restrict to void(T::mem_fun)():

#include <iostream>
struct foo {
    void func(){ std::cout << "foo"; }
};

template <typename T> struct get_type;
template <typename T> struct get_type<void(T::*)()> {
    using type = T;
};
template <typename T> using get_type_t = typename get_type<T>::type;


template<typename T, T F> void bar(){
    get_type_t<T> myfoo;
    (myfoo.*F)();
}

int main () {
    bar<decltype(&foo::func), &foo::func>();
}


来源:https://stackoverflow.com/questions/52317134/can-i-get-the-owning-object-of-a-member-function-template-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!