我可以获取成员函数模板参数的所属对象吗?

时间:2018-09-13 15:34:30

标签: c++ templates methods member-function-pointers metatype

给出一个对象:

struct foo {
    void func();
};

现在给出了模板化函数声明:

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

因此bar将采用如下的成员函数:

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

bar的正文中,我想从foo恢复类型T。我可以这样做吗?我希望能够执行以下操作:

get_obj<T> myfoo;

(myfoo.*F)();

我知道get_obj不是一回事,但是有办法写吗?

2 个答案:

答案 0 :(得分:13)

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>是成员函数F的类。

要处理const / volatile / etc,您最终必须做很多版本。真烦人这是一个示例:

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; \
}

可能想要:

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

指向const memfun的指针的类的类型是否为const类?

选择后,您需要编写上述宏的24种用法:

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;

我不知道如何避免对所有这24个专业进行全部覆盖。如果您认为这是愚蠢的,那是对的。请随时提出建议,向C ++标准委员会提出解决方案。

如果您要针对多个特征进行此类操作,则可以将“ strip lvalue,rvalue,noexcept和cv限定词”分开写成一个部分,并将它们分块传递。

Live example

答案 1 :(得分:7)

如果您限制为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>();
}