c++ - 如何生成具有推导签名的成员函数

标签 c++ metaprogramming template-meta-programming

是否可以生成方法定义(具有确切数量的参数和已知类型的返回值),具有:

  • 可变参数包中的方法参数类型“卡住”
  • 推导的方法返回类型
  • 方法名(传递给宏?)

详细信息:

我有一个简单的反射结构(为了可读性省略了部分特化的东西),它推导出成员函数返回类型和参数类型:

template<typename RetType, typename ...ArgTypes>
struct reflect_method<RetType(HostClassType::*)(ArgTypes...)> {
  using method_type = RetType;
  using method_args = type_placeholder<ArgTypes...>;
  using call_type = RetType(HostClassType::*)(ArgTypes...);
};

哪里method_type是一个方法返回类型,method_args是辅助模板结构中“卡住”的方法参数类型 type_placeholder .

我想做的是在生成的类中创建一个方法,该方法将反射(reflect)其他类的另一个方法的参数和返回类型。创建的方法将为反射的方法提供装饰。

伪代码实现:

#define RPCCLASS(class_name)    class RPC##class_name : public class_name   \
                                {                                           \
                                  using SelfType = RPC##class_name;         \
                                  using ParentType = class_name;

#define RPCCLASS_END()          };




#define RPCBIND(method_name)   \
    using method_name_##tag = reflect_method<decltype(ParentType::method_name)>; \
    method_name_##tag::method_type
    method_name(method_name_##tag::method_args::at<0>::type arg0, \
                method_name_##tag::method_args::at<1>::type arg1, \
                /* ... */                                         \
                /*don't know how to put correct number of arguments here)*/)    \
    {                                                                           \
      /* do some stuff */                                                       \
      /* ... */                                                                 \
      /* invoke the reflected method */                                         \
      return Invoke<method_name_##tag>::apply(this, method_name,                \
                                              arg0,                             \
                                              arg1                              \
             /*again don't know how to put correct number of arguments here)*/) \
     }


 // USAGE:
 class MyOwnClass {
 public:
   virtual long long doFun(int a, char b, const std::string& c);
 };


 RPCCLASS(MyOwnClass)
   RPCBIND(doFun)
 RPCCLASS_END()

最佳答案

我找到了一个解决方案。我没有尝试生成一个成员函数来反射(reflect)装饰方法,而是发现我可以生成一个成员函数。仿函数被实现为带有 operator()(...) 的模板结构。这使我能够在保留成员函数调用语义的同时使用正确数量的参数进行特化。

示例代码:

template <int Count>
struct apply_placeholders
{
};

template <>
struct apply_placeholders<1>
{
  template<typename CallType, typename Self, template<typename>class CallPtrType>
  static CallType apply(Self* self, CallPtrType<Self> callPtr)
  {
    return std::bind(std::mem_fn(callPtr), self, std::placeholders::_1);
  }
};
template <>
struct apply_placeholders<2>
{
  template<typename CallType, typename Self, template<typename>class CallPtrType>
  static CallType apply(Self* self, CallPtrType<Self> callPtr)
  {
    return std::bind(std::mem_fn(callPtr), self, std::placeholders::_1, std::placeholders::_2);
  }
};
template <>
struct apply_placeholders<3>
{
  template<typename CallType, typename Self, template<typename>class CallPtrType>
  static CallType apply(Self* self, CallPtrType<Self> callPtr)
  {
    return std::bind(std::mem_fn(callPtr), self, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
  }
};
template <>
struct apply_placeholders<4>
{
  template<typename CallType, typename Self, template<typename>class CallPtrType>
  static CallType apply(Self* self, CallPtrType<Self> callPtr)
  {
    return std::bind(std::mem_fn(callPtr), self, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
  }
};

template<typename RetType, template<typename...>class FrozenArgTypes, typename... ArgTypes>
struct mimic_functor_impl
{
};

template<typename RetType, typename... ArgTypes>
struct mimic_functor_impl<RetType, type_placeholder, type_placeholder<ArgTypes...>>
{
public:
  using CallType = std::function<RetType(ArgTypes...)>;
  template<typename Self>
  using CallPtrType = RetType(Self::*)(ArgTypes...);
private:
  CallType    mCall;

public:
  mimic_functor_impl(CallType call) : mCall{call}
  {
  }

  RetType operator () (ArgTypes... args)
  {
    return mCall(args...);
  }

  template<typename Self>
  static CallType make_function(Self* self, CallPtrType<Self> callPtr)
  {
    // manually specialise the template method because the compiler get's lost on matching "Self::*" in CallPtrType
    return apply_placeholders<sizeof...(ArgTypes)>::template apply<CallType, Self, CallPtrType>(self, callPtr);
  }
};

template<typename... ArgTypes>
struct mimic_functor_impl<void, type_placeholder, type_placeholder<ArgTypes...>>
{
public:
  using CallType = std::function<void(ArgTypes...)>;
  template<typename Self>
  using CallPtrType = void(Self::*)(ArgTypes...);
private:
  CallType        mCall;

public:
  mimic_functor_impl(CallType call) : mCall{call}
  {
  }

  void operator () (ArgTypes... args)
  {
    mCall(args...);
  }
  template<typename Self>
  static CallType make_function(Self* self, CallPtrType<Self> callPtr)
  {
    // manually specialise the template method because the compiler get's lost on matching "Self::*" in CallPtrType
    return apply_placeholders<sizeof...(ArgTypes)>::template apply<CallType, Self, CallPtrType>(self, callPtr);
  }
};

template<typename Reflect>
struct mimic_functor : mimic_functor_impl<typename Reflect::method_type, type_placeholder, typename Reflect::method_args>
{
private:
  using BaseType = mimic_functor_impl<typename Reflect::method_type, type_placeholder, typename Reflect::method_args>;
public:
  mimic_functor(typename BaseType::CallType call) : BaseType(call)
  {
  }
};



#define __TAG(x)     x ## _tag

#define RPCBIND(method_name) \  
        public: \
        using __TAG(method_name) = reflect_method<decltype(&ParentType::method_name)>; \
        mimic_functor<__TAG(method_name)> method_name{mimic_functor<__TAG(method_name)>::make_function(dynamic_cast<ParentType*>( const_cast<SelfType*>( this ) ), &ParentType::method_name)};

其余代码与问题 list 中的一样。

apply_placeholders 模板扩展了所需数量的占位符,以匹配可变参数包中的参数数量。

mimic_functor_implmimic_functor 模板创建其运算符 ()(...) 将匹配反射方法签名的仿函数。仿函数在被调用时也会调用反射方法。

make_function 成员模板函数创建一个绑定(bind)的 std::function,其中包含带有“this”指针的反射方法。

关于c++ - 如何生成具有推导签名的成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18329888/

相关文章:

c++ - 为什么编译时要在 std::initializer_list 中给出有关函数模板专门化的注释?

C++ : how can I fourier transform an array into an other array of different size using fftw3

c++ - 为什么std::deque的效率这么差?

ruby - 定义特定的 attr_accessor 方法以区分几种类型的实例变量

c++ - 模板函数无法将 'int' 转换为 nullptr_t

c++ - "Parameter set, but not used"模板函数中出现警告

ruby - 你如何在父类中打开一个类而不影响 ruby​​ 中的其他子类实例

c++ - 用自己的函数转换 mpl vector

c++ - 在 C++ 中实现和包装函数组合以进行惰性求值

没有虚函数的 C++ 动态调度