2011-11-06 79 views
3

如何(或有可能)用数字序列解压参数包?例如,如何使用数字序列解包可变参数模板参数?

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 <typename C, typename... T, size_t... N> 
C* init_from_tuple_impl(bp::tuple tpl) { 
    return new C{ bp::extract<T>(tpl[N])... }; 
} 

我们 “只是” 需要生成指数的包:

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

我们可以通过在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作出指示的地方只在某些情况下启用,也可能是模板参数需要一些变化,但这是一个开始。

相关问题