当将函数的签名输入模板时,尝试获得它们的签名相当容易,只需执行以下操作:
template <class OutType, class... ArgTypes>
void foo(OutType (*func)(ArgTypes...));
获得非静态成员函数仅稍微复杂一点:
template <class OutType, class MemberOf, class... ArgTypes>
void foo(OutType (MemberOf::*func)(ArgTypes...));
// or
template <class OutType, class MemberOf, class... ArgTypes>
void foo(OutType (MemberOf::*func)(ArgTypes...) const);
但是当输入方法是否为const无关紧要时,如何将上述两个函数声明准确地组合为一个?
const
不是可以与其所属的函数类型分开推断的特征。因此,如果要编写单个foo
模板声明,该声明仅限于接受指向成员的指针(但同时接受const
和非const
成员函数),则必须为:template <class MemberOf, class F>
void foo(F MemberOf::*func);
例如:
#include <type_traits> template <class MemberOf, class F> void foo(F MemberOf::*func) { static_assert(std::is_same<F, void(int) const>::value); } struct S { void bar(int) const {} }; int main() { foo(&S::bar); }
您无法在此时推断出F
的参数类型。您将不得不分派给助手功能。 (但是我们不能一次推导出所有类型,同时编写一个同时接受const
和非const
的声明。如果那是您唯一要接受的内容,那么抱歉,这是不可能的。)我们可以做像这样:
template <class T> struct remove_mf_const; template <class R, class... Args> struct remove_mf_const<R(Args...)> { using type = R(Args...); }; template <class R, class... Args> struct remove_mf_const<R(Args...) const> { using type = R(Args...); }; template <bool is_const, class F, class OutType, class MemberOf, class... ArgTypes> void foo_helper(F func, OutType (MemberOf::*)(ArgTypes...)) { // now you have all the types you need } template <class MemberOf, class F> void foo(F MemberOf::*func) { static_assert(std::is_function<F>::value, "func must be a pointer to member function"); using NonConstF = typename remove_mf_const<F>::type; constexpr bool is_const = !std::is_same<F, NonConstF>::value; foo_helper<is_const>(func, (NonConstF MemberOf::*)nullptr); }
Coliru link