2010-04-08 5 views
4

나는 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

귀하의 질문과 관련이 없지만'safe_delete'는 무엇입니까? – GManNickG

+0

그냥 포인터를 삭제하고 NULL로 설정되었는지 확인하는 방법. 또한 char * 및 벡터 – Lodle

+0

Alright와 같은 다양한 유형의 오버로드가 있습니다. :) 삭제하기 전에 null을 확인하지 않는 한 "행복합니다. : P (null을 삭제하면 완전히 안전합니다.) – GManNickG

답변

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을 처리하면 모두 설정됩니다!

+0

당신은 전 처리기의 헛소리와 함께 다시 간다. :) – GManNickG

+0

와우 그 누구도 그것을 바꿀 수 없을 것입니다. 내가 2 개의 가장 좋은 해답을 줄 수 있기를 바란다. – Lodle

+0

'@ GMan' : 나는 전 처리기로 놀아서 즐기는 것을 인정해야한다 :)'@ Lodle' : 당신이 바라는대로 수락하고, 나는 XP를 많이 신경 쓰지 않는다. 유지 보수에 관해서는, 나는 조금 어색 할 수도 있음을 인정한다. 하지만 진정한 버머는 디버깅을하고있다.)'gcc'에서'-E' 옵션을 잊어 버려서 전 처리기 출력을 얻지 못한다! –

2

훨씬 당신이 할 수 없다. Boost.Preprocessor을 사용하여 함수를 생성 할 수 있지만 옵션 인 경우 Boost.Bind 라이브러리를 사용할 수도 있습니다.

또한 정상적인 기능

당신은 실제로 할 수

으로 무효 기능을 처리하는 방법이있다. 다음은 a-ok입니다.

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); 
} 

그냥 정상처럼 호출하고 반환 형식 인 경우 voidRvoid을 넣어 :


은 그래서 당신이 원하는 것 같습니다. 반품은 return;으로 처리됩니다.

그러면 문제는 handleReturn 기능이됩니다. Rvoid인지 여부에 따라 올바른 함수로 라우팅하려면 컴파일 타임 if 문이 필요합니다. 다음은 기본 유형 - 특성 (유형에 대한 이러한 쿼리가 호출 됨)입니다. 프레임 워크 :

// 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" 

이것은 유형 형질 시스템의 핵심입니다. 고려 : 여부 B에 따라

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>()); 
} 

사실인지, 우리 것 foo의 다른 버전 중 하나를 true_tag 변형, 또는 false_tag 변형 노선. 계속 진행하기 전에이 부분을 반드시 이해하십시오.

템플릿 특수화를 사용하여 bool_type에서 상속되는 유형을 생성하고 해당 특성이 true인지에 따라 true_type 또는 false_type 중 하나입니다.

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 여부

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 반환 유형에 대한 우려가 최소화됩니다.

+0

귀하의 예제가 임의의 인수 번호 문제와 어떻게 대응하는지 볼 수 없습니다. +1 Boost.Bind의 경우 – Basilevs

+0

일반 템플릿에서 void를 사용하기가 어렵 기 때문에 반환 유형에 대해 얘기했습니다. – Lodle

+0

@Basilevs : "일반적인 함수처럼 void 함수를 처리하는 방법도 있습니다."하지만 이제는 다 해결해 보았습니다. – GManNickG