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__ 函数,该函数接受具有预定义类型的元组。

4

2 回答 2

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>
]':

正是我们想要的:)

于 2011-11-06T16:11:31.333 回答
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'senable_if使指示的位置仅在某些情况下启用,并且模板参数可能需要一些更改,但这是一个开始。

于 2011-11-06T15:23:49.533 回答