【问题标题】: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;
}

【问题讨论】:

    标签: c++ templates member-function-pointers


    【解决方案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建议的“通话”一体化版本
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-07
      • 1970-01-01
      • 2021-03-04
      相关资源
      最近更新 更多