3

내 프로젝트 중 하나에 luabind을 포함시키고 싶습니다. 그렇게하려면 call_function (아래 참조)과 비슷한 동작을 제공해야합니다. 이 함수는 몇 가지 템플릿 마법을 사용합니다 (Boost의 호의). 템플릿 메타 프로그래밍을 처음 접한 것은 이번이 처음입니다. 그래서 저는 조금 잃었습니다. 다음은 도움을 주시면 감사하겠습니다.가변 길이 인수 BOOST_PP_ITERATION

#define LUABIND_TUPLE_PARAMS(z, n, data) const A##n * 
#define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n 

나는이 처리기 비트, 나는 심지어는 너무 검색이라고 모르겠어요까지 무엇인지 정말 모르겠어요 조금 어렵습니다. A은 템플릿 유형입니다. 내가 정확히 #a을 기억한다면 리터럴 텍스트 a을 삽입 하겠지만, 복수 #은 무엇을합니까? 이 전처리기 물건이 나온 후에.

template<class Ret BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)> 
    typename boost::mpl::if_<boost::is_void<Ret> 
      , luabind::detail::proxy_function_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > 
      , luabind::detail::proxy_function_caller<Ret, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type 
    call_function(lua_State* L, const char* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _)) 
    { 
     typedef boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> tuple_t; 
#if BOOST_PP_ITERATION() == 0 
     tuple_t args; 
#else 
     tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a)); 
#endif 

    } 

보시다시피 Boost를 많이 사용합니다. 내가 봤는데 BOOST_PP_ITERATION 봤어하지만 여전히 정말 뭐하는거야 밖으로 만들 수 없습니다. 누군가이 코드의 문맥에서 제게 설명해 주시겠습니까? BOOST_PP의 내용과 args에 인수를 가져 오는 방법을 설명하는 것이 좋습니다.

내 목표는 내가 정의 할 call_function의 오버로드로 전달할 수있는 args을 생성 할 내 코드 내에서 call_function을 정의하는 것입니다. 즉, 동일한 호출 규칙을 사용할 수 있지만 luabind을 호출하기 전에 일부 사전 처리를 적용 할 수도 있습니다.

이 질문은 제가 말한 방식으로 매우 구체적입니다. 그러나이 개념은 여기에서 OK 일 정도로 충분히 일반적이라고 생각합니다.

+0

[Boost.Preprocessor] (http://www.boost.org/doc/libs/1_52_0/libs/preprocessor/doc/index.html) 설명서를 참조하십시오. – TemplateRex

답변

3

BOOST_PP_ *는 템플릿 메타 프로그래밍과 관련이 없으며 전처리 기 라이브러리입니다. 이름에서 알 수 있듯이, 그것은 전처리 기 마법으로 작동하며, 비슷한 템플릿을 생성하기 위해 정말로 힘든 일을합니다. 귀하의 경우, 즉 다음과 같습니다

//preprocessor iteration 0 
template<class Ret> 
    typename boost::mpl::if_<boost::is_void<Ret> 
      , luabind::detail::proxy_function_void_caller<boost::tuples::tuple<> > 
      , luabind::detail::proxy_function_caller<Ret, boost::tuples::tuple<> > >::type 
    call_function(lua_State* L, const char* name) 
    { 
     typedef boost::tuples::tuple<> tuple_t; 
     tuple_t args; 
    } 

//preprocessor iteration 1 
template<class Ret , class A0> 
typename boost::mpl::if_<boost::is_void<Ret> 
     , luabind::detail::proxy_function_void_caller<boost::tuples::tuple<const A0 *> > 
     , luabind::detail::proxy_function_caller<Ret, boost::tuples::tuple<const A0 *> > >::type 
call_function(lua_State* L, const char* name , const A0 & a0) 
{ 
    typedef boost::tuples::tuple<const A0 *> tuple_t; 
    tuple_t args(&a0); 
} 

등 (예 : A0, A1, A2, A3... A9 최대 10 인 경우) 다른 곳에서 정의 된 일부 최대

##는 처리기에 대한 토큰을 연결 한 최대, 이 경우에 n 값 (=> A0, A1, A2, ...)이있는 연결 A (또는 a). 전체 코드는 일부 사전 처리 루프에 있습니다. 인수가 0이, 예를하지 않은 경우

  • BOOST_PP_ITERATION()

    은, (0, 1, 2 ...)
  • BOOST_PP_COMMA_IF(X) 쉼표를주는 전류 루프 인덱스를 준다 템플릿 매개 변수 목록의 반복 1에서 "클래스 A0"앞에있는 쉼표
  • BOOST_PP_ENUM(n,B,C)은 N이 0 .. (n-1), 즉 매크로가 실행되는 B (?, N, C)의 쉼표로 구분 된 목록을 제공합니다. B는 n 번 실행되므로 BOOST_PP_ENUM (3, LUABIND_TUPLE_PARAMS, _)을 호출하면 const A0 *, const A1 *, const A2 *
  • BOOST_PP_ENUM_PARAMS(n, X)은 쉼표로 구분 된 X ## n의 목록을 제공합니다그것은 첫눈에 이해하기 쉬운 일이 아닙니다), 당신은 운이 좋다면 당신은 다시 물건을 건너되지 않도록 그 처리기 마법의 사용 사례의 대부분 BOOST_PP_ENUM_PARAMS(3, &a)

에 대한 &a0, &a1, &a2는 요즘 가변 인자 템플릿을 사용하여 수행 할 수 있습니다 전처리는 다른 알려진 C++ 기능처럼 작동하지 않으며 해결해야하는 몇 가지 한계가 있기 때문에 이해하기가 쉽지 않습니다.