如何(或是否可以)用数字序列解压缩参数包?例如,
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__函数,该函数接受具有预定义类型的元组。
答案 0 :(得分: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 :(得分: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);
}
使用boost enable_if
可以使指示的位置仅在某些情况下启用,并且模板参数可能需要进行一些更改,但这是一个开始。