推断拥有成员函数的类的类型

Posted

技术标签:

【中文标题】推断拥有成员函数的类的类型【英文标题】:Infer the type of the class owning a member function 【发布时间】:2020-09-01 11:33:48 【问题描述】:

让我们考虑一种“调用”函数(这里称为“调用”),它有助于调用由模板参数传递的成员函数。 在这个函数中,我需要知道拥有成员函数的类的类型。有没有办法(最好在 c++14 中)这样做?

#include <functional>

template<typename F, typename... Args, std::enable_if_t<std::is_member_pointer<std::decay_t<F>>, int> = 0 >
constexpr decltype(auto) call(F&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))

    // Here we know that f is a member function, so it is of form : &some_class::some_function
    // Is there a way here to infer the type some_class from f ? For exemple to instantiate a variable from it :
    // imaginary c++ : class_of(f) var;
    return std::mem_fn(f)(std::forward<Args>(args)...);


int main()

    struct Foo  void bar()   foo;
    call(&Foo::bar, &foo /*, args*/);
    return 0;

【问题讨论】:

【参考方案1】:
template <typename>
struct class_of;
template <typename C, typename R, typename... Args>
struct class_of<R(C::*)(Args...)> 
    using type = C;
;

然后你可以得到typename class_of&lt;F&gt;::type这样的类型。例如

template<typename F, typename... Args, std::enable_if_t<std::is_member_pointer<std::decay_t<F>>, int> = 0 >
constexpr decltype(auto) call(F&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))

    typename class_of<F>::type var;
    return std::mem_fn(f)(std::forward<Args>(args)...);

顺便说一句,这取决于您的意图,但您可以更改模板参数的声明以直接获取类类型。

// I remove the type check because only member function pointer could be passed in
template<typename C, typename R, typename... FArgs, typename... Args>
constexpr decltype(auto) call(R(C::*f)(FArgs...), Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))

    C var;
    return std::mem_fn(f)(std::forward<Args>(args)...);

【讨论】:

【参考方案2】:

songyuanyao 击败了我,但请注意,您不需要拼出函数类型来解构成员指针:

template <class MemberPtr>
struct mptr_class;

template <class T, class Class>
struct mptr_class<T Class::*> 
    using type = Class;
;

template <class MemberPtr>
using mptr_class_t = typename mptr_class<MemberPtr>::type;

【讨论】:

感谢您的简化,这也适用于songyuanyao建议的“通话”一体化版本

以上是关于推断拥有成员函数的类的类型的主要内容,如果未能解决你的问题,请参考以下文章

指向具有私有构造函数的类的类成员的指针

具有引用数据成员的类的默认构造函数?

可以是类型或工厂函数的类成员的不同行为

6——在类的外部定义成员函数

类的其他特性

CPP复习笔记 2