5

У меня есть следующий код база:Функция принимает как указатель на член-функцию и указатель на константный член-функцию

template <typename Type> 
class SomeClass { 
public: 
    template <typename ReturnType, typename... Params> 
    void register_function(const std::pair<std::string, ReturnType (Type::*)(Params...)> fct) { 
     auto f = [fct](Params... params) -> ReturnType { return (Type().*fct.second)(std::ref(params)...); } 
     // ... 
    } 
}; 

Это работает, когда я передать указатель на член-функцию (неконстантная). Однако, если я хочу передать указатель на константный член-функции, это приводит к ошибке компиляции, и я должен дублировать функции выше, чтобы получить этот код:

template <typename Type> 
class SomeClass { 
public: 
    template <typename ReturnType, typename... Params> 
    void register_function(const std::pair<std::string, ReturnType (Type::*)(Params...)> fct) { 
     auto f = [fct](Params... params) -> ReturnType { return (Type().*fct.second)(std::ref(params)...); } 
     // ... 
    } 

    template <typename ReturnType, typename... Params> 
    void register_function(const std::pair<std::string, ReturnType (Type::*)(Params...) const> fct) { 
     auto f = [fct](Params... params) -> ReturnType { return (Type().*fct.second)(std::ref(params)...); } 
     // ... 
    } 
}; 

Теперь я могу передать как const- члены-функции и не-const-члены-функции. Но теперь код дублируется, а ремонтопригодность сокращается.

Есть ли способ объединить эти две функции в функцию, принимающую как const-члены-функции, так и не-const-member-функции?

Важное замечание: я действительно должен использовать функцию указателя как параметр (no std :: function).

Редактировать: Я добавил еще немного кода. Внутри функций я строю замыкание, соответствующее сигнатуре функции-члена (такие же типы возврата и параметры). Это замыкание будет храниться и использоваться в дальнейшем для создания отражения (more here)

+0

Почему не просто 'шаблон <имяТипа Fun> аннулируются register_function (Fun ГЦТ)'? – fredoverflow

+0

Я обновляю свой вопрос с помощью немного кода. Внутри лямбда я могу вызвать std :: bind или напрямую использовать указатель функции-члена в экземпляре нового объекта. Вот почему мне действительно нужно получить доступ к типам ReturnType и Params. –

+0

Это весь ваш код? lol really –

ответ

5

Вы могли бы написать тип признака, на основании которого будет сообщать вам, если некоторые MF функция указатель на член на Type:

template <typename C, typename T> 
struct is_pointer_to_member_helper : std::false_type { }; 

template <typename C, typename T> 
struct is_pointer_to_member_helper<C, T C::*> : std::is_function<T> { }; 

template <typename C, typename T> 
struct is_pointer_to_member : is_pointer_to_member_helper<C, 
            std::remove_cv_t<T> 
           > { }; 

и использовать его, чтобы убедиться, что вы получите только один из них:

template <typename Type> 
class SomeClass { 
public: 
    template <typename MF> 
    std::enable_if_t<is_pointer_to_member<Type, MF>::value> 
    register_function(const std::pair<std::string, MF> fct) 
    { 
     auto f = [fct](auto&&... params) { 
      return (Type{}.*fct.second)(std::forward<decltype(params)>(params)...); 
     }; 

     // ... 
    } 
}; 
+0

У нас есть 'std :: is_member_function_pointer' –

+0

@ T.C. Не знал этого. Я думаю, все еще хочу явно проверить, какой класс является указателем на функцию-член. – Barry

+0

Интересный ответ. Однако мне нужно получить доступ к типам ReturnType и Params .... Я обновил свой вопрос еще немного кода: я использую lambdas в своем коде, где я могу вызвать std :: bind или напрямую использовать указатель на новый экземпляр Type. –

Смежные вопросы