3

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

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

细节:

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

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是方法参数类型“冻结”在辅助模板 structtype_placeholder中。

我正在尝试做的是在生成的类中创建一个方法,该方法将反映参数和返回某个其他类的另一个方法的类型。创建的方法将为反射方法提供装饰。

伪代码实现:

#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()
4

1 回答 1

2

我找到了解决方案。我发现我可以生成一个成员函数,而不是尝试生成一个成员函数来反映一个修饰的方法。函子被实现为带有 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)};

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

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

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

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

于 2013-08-20T14:09:54.253 回答