C++ 如何在模板中输入常量和非常量成员函数时避免代码重复

C++ 如何在模板中输入常量和非常量成员函数时避免代码重复,c++,c++11,templates,methods,constants,C++,C++11,Templates,Methods,Constants,当函数输入到模板中时,尝试获取其签名时,只需执行以下操作: template <class OutType, class... ArgTypes> void foo(OutType (*func)(ArgTypes...)); 模板 void foo(OutType(*func)(ArgTypes…); 获取非静态成员函数只是稍微复杂一些: template <class OutType, class MemberOf, class... ArgTypes> void

当函数输入到模板中时,尝试获取其签名时,只需执行以下操作:

template <class OutType, class... ArgTypes>
void foo(OutType (*func)(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);
模板
void foo(OutType(MemberOf::*func)(ArgTypes…);
//或
模板
void foo(OutType(MemberOf::*func)(ArgTypes…)const);

但是,当输入方法是否为const无关紧要时,如何将上述两个函数声明合并为一个呢?

不幸的是,非静态成员函数上是否存在const并不是一个可以从其所属的函数类型中单独推断出来的特征。因此,如果您想编写一个
foo
模板声明,该声明仅限于接受指向成员的指针(但同时接受
const
和非
const
成员函数),那么它必须是:

template <class MemberOf, class F>
void foo(F MemberOf::*func);

取决于您需要的
模板void foo(Func Func)
是我的第一个选择。@NathanOliver我需要签名中的所有类型,不幸的是,我需要在函数中找到。我同意Nathan,使用
std::invoke
可以支持的不仅仅是函数pointers@MatthewL在这种情况下,
templatevoidfoo(std::function)如何处理?这似乎是可行的,但是
foo(std::function(&bar::do))
感觉不必要的冗长,特别是对于描述性函数/类名
#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);
}
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);
}