2011-11-06 4 views
3

숫자 시퀀스가있는 매개 변수 팩의 압축을 푸는 방법 (또는 가능합니까?)? 예를 들어,variadic 템플릿 매개 변수의 숫자 시퀀스를 압축 해제하는 방법은 무엇입니까?

template <typename C, typename... T> 
C* init_from_tuple(bp::tuple tpl) 
{ 
    return new C{bp::extract<T>("magic"(tpl))...}; // <-- 
} 

되는 <-- 라인은

return new C{bp::extract<T0>(tpl[0]), 
       bp::extract<T1>(tpl[1]), 
       ..... 
       bp::extract<Tn>(tpl[n])}; 

n == sizeof...(T) - 1로 확대 될 전망이다.

목적은 사전 정의 된 유형의 튜플을 허용하는 Boost.Python을위한 __init__ 함수를 만드는 것입니다.

답변

3

사실, 언팩 작업은 두 개의 다른 매개 변수 세트를 동시에 대상으로 지정할 수 있습니다 (동일한 길이가되어야한다고 생각합니다). 여기서 우리는 유형의 팩과 숫자의 팩을 원합니다.

뭔가 유사로 : 사용 후

template <size_t... N> struct Collection {}; 

template <typename C> struct ExtendCollection; 

template <size_t... N> 
struct ExtendCollection< Collection<N...> > { 
    typedef Collection<N..., sizeof...(N)> type; 
}; 

template <typename... T> 
struct GenerateCollection; 

template <> 
struct GenerateCollection<> { typedef Collection<> type; }; 

template <typename T0, typename... T> 
struct GenerateCollection<T0, T...> { 
    typedef typename ExtendCollection< 
    typename GenerateCollection<T...>::type 
    >::type type; 
}; 

그리고 :

template <typename C, typename... T, size_t... N> 
C* init_from_tuple_impl(bp::tuple tpl, Collection<N...>) { 
    return new C { bp::extract<T>(tpl[N])... }; 
} 

template <typename C, typename... T> 
C* init_from_tuple(bp::tuple tpl) { 
    typename GenerateCollection<T...>::type collection; 
    return init_from_tuple_impl<C, T...>(tpl, collection); 
} 

을 행동에 Ideone에서

template <typename C, typename... T, size_t... N> 
C* init_from_tuple_impl(bp::tuple tpl) { 
    return new C{ bp::extract<T>(tpl[N])... }; 
} 

우리는 "그냥"지수의 팩을 생성해야 .

우리는 init_from_tuple_impl의 구현 (예를 들어, new 제거)에 "실수"를함으로써 정확성을 목격 할 수

:

행동
template <typename C, typename... T, size_t... N> 
C* init_from_tuple_impl(bp::tuple tpl, Collection<N...>) { 
    return C { bp::extract<T>(tpl[N])... }; 
} 

Ideone에서 :

prog.cpp: In function 'C* init_from_tuple_impl(bp::tuple, Collection<N ...>) 
[with 
    C = bp::Object, 
    T = {int, float, char}, 
    unsigned int ...N = {0u, 1u, 2u}, 
    bp::tuple = std::basic_string<char> 
]': 

정확히 무엇을 우리 ~ 싶었어.

1

먼저 매개 변수를 자체 팩에 추출한 다음 생성자를 호출하면 가능합니다. 그것에서 멀리 완료,하지만 당신은 일반적인 아이디어를 얻을 :

template <typename C, int N, typename... T> 
C* init_from_tuple(bp::tuple tpl, T... args) // enable_if N == sizeof...(T) 
{ 
    return new C{args...}; 
} 

template <typename C, int N, typename T0, typename... T> 
C* init_from_tuple(bp::tuple tpl, T... args) // enable_if N != sizeof...(T) 
{ 
    return init_from_tuple<C, N + 1>(tpl, args, bp::extract<T0>(tpl[N])); 
} 

template <typename C, typename... T> 
C* init_from_tuple(bp::tuple tpl, T... args) 
{ 
    return init_from_tuple<C, 0, T...>(tpl, args); 
} 

사용 부스트의 enable_if 표시된 장소는 어떤 경우에 사용 가능하고, 아마 템플릿 인수가 일부 변경이 필요하지만, 이것은 시작되어 있는지 확인합니다.

관련 문제