Можно ли получить объект-владелец параметра шаблона функции-члена?

Дан объект:

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 не вещь, но был бы способ написать это?

10

Решение

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 / и т.д. вам придется сделать кучу версий. Это раздражает. Вот пример этого:

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 является константным классом или нет?

После того, как вы выбрали, вам нужно написать 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» и передать их по частям.

Живой пример.

12

Другие решения

Если вы ограничиваете 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>();
}
6

По вопросам рекламы [email protected]