我有一堆用于rpc的模板,并且想知道是否有一种方法可以简化它们,因为它重复它自我分配。我知道模板的varags会出现在下一个标准中,但你能为模板做默认值吗?
还有办法将void返回函数作为普通函数处理吗? Atm我必须将它们分开并将它们视为两个不同的东西,因为模板不会因为类型而变得无效。
template <typename R>
R functionCall(IPC::IPCClass* c, const char* name)
{
IPC::IPCParameterI* r = c->callFunction( name, false );
return handleReturn<R>(r);
}
template <typename R, typename A>
R functionCall(IPC::IPCClass* cl, const char* name, A a)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a));
return handleReturn<R>(r);
}
template <typename R, typename A, typename B>
R functionCall(IPC::IPCClass* cl, const char* name, A a, B b)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a), IPC::getParameter(b) );
return handleReturn<R>(r);
}
template <typename R, typename A, typename B, typename C>
R functionCall(IPC::IPCClass* cl, const char* name, A a, B b, C c)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c) );
return handleReturn<R>(r);
}
template <typename R, typename A, typename B, typename C, typename D>
R functionCall(IPC::IPCClass* cl, const char* name, A a, B b, C c, D d)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c), IPC::getParameter(d) );
return handleReturn<R>(r);
}
template <typename R, typename A, typename B, typename C, typename D, typename E>
R functionCall(IPC::IPCClass* cl, const char* name, A a, B b, C c, D d, E e)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c), IPC::getParameter(d), IPC::getParameter(e) );
return handleReturn<R>(r);
}
template <typename R, typename A, typename B, typename C, typename D, typename E, typename F>
R functionCall(IPC::IPCClass* cl, const char* name, A a, B b, C c, D d, E e, F f)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c), IPC::getParameter(d), IPC::getParameter(e), IPC::getParameter(f) );
return handleReturn<R>(r);
}
inline void functionCallV(IPC::IPCClass* cl, const char* name)
{
IPC::IPCParameterI* r = cl->callFunction( name, false );
handleReturnV(r);
}
template <typename A>
void functionCallV(IPC::IPCClass* cl, const char* name, A a)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a));
handleReturnV(r);
}
template <typename A, typename B>
void functionCallV(IPC::IPCClass* cl, const char* name, A a, B b)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a), IPC::getParameter(b) );
handleReturnV(r);
}
template <typename A, typename B, typename C>
void functionCallV(IPC::IPCClass* cl, const char* name, A a, B b, C c)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c) );
handleReturnV(r);
}
template <typename A, typename B, typename C, typename D>
void functionCallV(IPC::IPCClass* cl, const char* name, A a, B b, C c, D d)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c), IPC::getParameter(d) );
handleReturnV(r);
}
template <typename A, typename B, typename C, typename D, typename E>
void functionCallV(IPC::IPCClass* cl, const char* name, A a, B b, C c, D d, E e)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c), IPC::getParameter(d), IPC::getParameter(e) );
handleReturnV(r);
}
template <typename A, typename B, typename C, typename D, typename E, typename F>
void functionCallV(IPC::IPCClass* cl, const char* name, A a, B b, C c, D d, E e, F f)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c), IPC::getParameter(d), IPC::getParameter(e), IPC::getParameter(f) );
handleReturnV(r);
}
inline void functionCallAsync(IPC::IPCClass* cl, const char* name)
{
IPC::IPCParameterI* r = cl->callFunction( name, true );
handleReturnV(r);
}
template <typename A>
void functionCallAsync(IPC::IPCClass* cl, const char* name, A a)
{
IPC::IPCParameterI* r = cl->callFunction( name, true, IPC::getParameter(a));
handleReturnV(r);
}
template <typename A, typename B>
void functionCallAsync(IPC::IPCClass* cl, const char* name, A a, B b)
{
IPC::IPCParameterI* r = cl->callFunction( name, true, IPC::getParameter(a), IPC::getParameter(b) );
handleReturnV(r);
}
template <typename A, typename B, typename C>
void functionCallAsync(IPC::IPCClass* cl, const char* name, A a, B b, C c)
{
IPC::IPCParameterI* r = cl->callFunction( name, true, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c) );
handleReturnV(r);
}
template <typename A, typename B, typename C, typename D>
void functionCallAsync(IPC::IPCClass* cl, const char* name, A a, B b, C c, D d)
{
IPC::IPCParameterI* r = cl->callFunction( name, true, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c), IPC::getParameter(d) );
handleReturnV(r);
}
template <typename A, typename B, typename C, typename D, typename E>
void functionCallAsync(IPC::IPCClass* cl, const char* name, A a, B b, C c, D d, E e)
{
IPC::IPCParameterI* r = cl->callFunction( name, true, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c), IPC::getParameter(d), IPC::getParameter(e) );
handleReturnV(r);
}
template <typename A, typename B, typename C, typename D, typename E, typename F>
void functionCallAsync(IPC::IPCClass* cl, const char* name, A a, B b, C c, D d, E e, F f)
{
IPC::IPCParameterI* r = cl->callFunction( name, true, IPC::getParameter(a), IPC::getParameter(b), IPC::getParameter(c), IPC::getParameter(d), IPC::getParameter(e), IPC::getParameter(f) );
handleReturnV(r);
}
根据要求提供额外代码:
template <typename R>
R handleReturn(IPC::IPCParameterI* r)
{
if (r->getType() == PException::getTypeS())
{
gcException gce((gcException*)r->getValue());
safe_delete(r);
throw gce;
}
R temp = IPC::getParameterValue<R>(r, true);
safe_delete(r);
return temp;
}
inline void handleReturnV(IPC::IPCParameterI* r)
{
if (r->getType() == PException::getTypeS())
{
gcException gce((gcException*)r->getValue());
safe_delete(r);
throw gce;
}
safe_delete(r);
return;
}
答案 0 :(得分:2)
对于变量参数,您无能为力。您可以使用Boost.Preprocessor生成函数,但如果这是一个选项,您也可以使用他们的Boost.Bind库。
还有一种方法可以将void函数作为普通函数来处理
你真的可以。以下是一个好的:
void foo(void)
{
// sup
}
void bar(void)
{
return foo();
}
void baz(void)
{
return bar();
}
void lolwut(void)
{
return baz();
}
它只是没有做任何事情,回归。
所以你想要的是:
// snipping for conciseness, obviously this applies to all variants
template <typename R>
R functionCall(IPC::IPCClass* c, const char* name)
{
IPC::IPCParameterI* r = c->callFunction( name, false );
return handleReturn<R>(r);
}
template <typename R, typename A> // taking as const& to avoid copy
R functionCall(IPC::IPCClass* cl, const char* name, const A& a)
{
IPC::IPCParameterI* r = cl->callFunction( name, false, IPC::getParameter(a));
return handleReturn<R>(r);
}
您只需按正常方式调用它,当返回类型为void
时,将void
设为R
。退货将被视为return;
。
然后问题变为handleReturn
函数。您需要一个编译时if语句,以根据R
是否为void
来路由到正确的函数。这是一个基本的类型特征(就类型的查询而言)框架:
// any constant-expression can be turned into a type
// that can be instantiated, true and false generate
// different types
template <bool B>
struct bool_type
{
static const bool value = B;
};
// the two fundamental types that will be generated
typedef bool_type<true> true_type; // the expression was true
typedef bool_type<false> false_type; // the expression was false
// mark functions that take a bool_type result...
typedef const true_type& true_tag; // ...as "the result was true"
typedef const false_type& false_tag; // ...or "the result was false"
这是类型特征系统的核心。考虑:
void foo(true_tag); // B was true
void foo(false_tag); // B was not true
void foo(void)
{
static const bool B = true;
foo( bool_type<B>() );
}
根据B
是否为真,我们将转到不同版本的foo
,true_tag
变体或false_tag
变体。在继续之前,请确保您理解这一部分。
我们现在使用模板特化来生成一个继承自bool_type
的类型,并且是true_type
或false_type
,具体取决于该特征是否为真。对我们来说:
template <typename T> // in general, T is not a void...
struct is_void : bool_type<false>
{
typedef T type;
};
template <> // ...but in this case it is
struct is_void<void> : bool_type<true>
{
typedef void type;
};
现在我们可以根据某种类型void
选择一个函数:
void foo(true_tag); // R was void
void foo(false_tag); // R was not void
template <typename R>
void foo(void)
{
// either inherits from true_type or false_type
// and goes to the respective function
foo( is_void<R>() );
}
或适用于我们的情况:
// I put all my detail functions in a namespace called detail,
// whether or not you do the same is up to you
namespace detail
{
template <typename R> // not void variant
R getReturn(IPC::IPCParameterI* r, false_tag)
{
R temp = IPC::getParameterValue<R>(r, true);
safe_delete(r);
return temp;
}
template <typename R> // void variant
R getReturn(IPC::IPCParameterI*, true_tag)
{
// do nothing
}
}
template <typename R>
R handleReturn(IPC::IPCParameterI* r)
{
// applies to both
if (r->getType() == PException::getTypeS())
{
gcException gce((gcException*)r->getValue());
safe_delete(r);
throw gce;
}
// but now route to the correct version
return detail::getReturn<R>(r, is_void<R>());
}
此代码对void
返回类型的关注重复最少。
答案 1 :(得分:2)
太棒了!让我们玩得开心:))
实际上可以在没有varargs的情况下自动计算所有这些模板。它只需要预编程器编程,所以首先让我们看一下Boost.Preprocessor。
首先,我们需要设计一个宏来处理实际的函数定义:
#define FUNCTION_CALL_IPC(z, n, data)\
IPC::getParameter( BOOST_PP_CAT(data, n) )
#define FUNCTION_CALL(z, n, data) \
template < \
class R \
BOOST_ENUM_TRAILING_PARAM(n, class Arg) \
> \
R functionCall(IPC::IPCClass* cl, const char* name \
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(n, Arg, const& arg) \
) \
{ \
IPC::IPCParameterI* r = cl->callFunction(name, false \
BOOST_PP_ENUM_TRAILING(n, FUNCTION_CALL_IPC, arg) \
); \
return handleReturn<R>(r); \
}
// From 0 to 9 arguments
BOOST_PP_REPEAT(10, FUNCTION_CALL, ~)
瞧。
结合Gman处理void
的诀窍,你已经完成了!