gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 21:45:07 26 4
gpt4 key购买 nike

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

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

详细信息:

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

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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com