如何避免将const和非const成员函数输入模板的代码重复

时间:2019-10-03 18:20:22

标签: c++ c++11 templates methods const

在将函数的特征符输入到模板中时尝试获得它们的签名相当容易,只需执行以下操作:

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无关紧要时,如何将上述两个函数声明准确地组合为一个?

1 个答案:

答案 0 :(得分:4)

不幸的是,非静态成员函数上是否存在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

相关问题