如何从一个旧的元组和一个boost中的类型创建一个新的元组类型? [英] How to create a new tuple type from an old one and a type in boost?

查看:112
本文介绍了如何从一个旧的元组和一个boost中的类型创建一个新的元组类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个元组类型.我想在其中添加元素类型以获得新的元组类型.我可以做到

I have a tuple type. I want to add a element type in it to get a new tuple type. I can do it like

decltype tuple_cat(MyTuple, std::tuple<MyType>())

但是,我在boost::tuple中找不到tuple_cat,如何在boost中做到这一点?

However, I don't find tuple_cat in boost::tuple, how to do it in boost?

推荐答案

我认为您希望在编译时就拥有所有这些功能.

I assume you want all this in compile time.

这是一般的解释:连接元组类似于连接列表或数组,只是算法相同.在这里,给定元组ab,我选择将a的最后一个元素移动到b的开头,并重复直到a为空.

Here is the general explanation: concatening tuples is similar to concatening lists or arrays, is that the algorithm is the same. Here, given tuples a and b, I choosed to move the last element of a to the beginning of b, and repeat until a is empty.

第一:基础结构.以下结构保留了一个参数包.它可以是任何东西,例如元组:

First: base structures. The following structure keeps a parameter pack. It can be anything, for example a tuple:

template<typename... T>
struct pack
{
    static const unsigned int size = sizeof...(T);
};

请注意,包装的大小存储在其中.它不是强制性的,但是便于解释. Boost使用结构boost::tuples::length<T>::value(更详细).

Note that the size of the pack is stored inside it. It is not mandatory, but it is convenient for the explanation. Boost uses the struct boost::tuples::length<T>::value (which is more verbose).

要访问第i个位置的元素,我们使用类似于boost::tuples::element<n, T>的结构:

To access an element at i-th position, we use a structure similar to boost::tuples::element<n, T>:

// Get i-th element of parameter pack
// AKA 'implementation'
// Principle: the element i is the first element of the sub-array starting at indice i-1
template<int n, typename F, typename... T>
struct element_at : public element_at<n-1, T...>
{
};

template<typename F, typename... T>
struct element_at<0, F, T...>
{
    typedef F type;
};

// Get i-th element of pack
// AKA 'interface' for the 'pack' structure
template<int n, typename P>
struct element
{
};

template<int n, typename... T>
struct element<n, pack<T...>>
{
    typedef typename element_at<n, T...>::type type;
};

现在,我们必须使用低级操作,该操作将一个元素添加到包的一侧(在左侧或右侧添加).这里选择了在左侧添加,但这不是唯一的选择:

Now, we must use a low-level operation which is adding one element to a side of a pack (adding at left or at right). Here adding at left is choosed, but it is not the only choice:

// Concat at left (only for structure 'pack')
template<typename a, typename b>
struct tuple_concat_left
{
};

template<typename a, typename... b>
struct tuple_concat_left<a, pack<b...>>
{
    typedef pack<a, b...> type;
};

对于模板,a不会更改,而是使用索引来了解要添加的元素.继承定义了一个'type'typedef,它是n之后的所有索引和另一个元组(不包括n,按顺序)的所有索引的串联.我们只需要在左侧将元素连接到索引n.

For templates, a is not changed, and instead we use an indice to know what element to add. The inheritance define a 'type' typedef which is the concatenation of all indices after n and the other tuple (not including n, and in order). We just have to concatenate at left the element at indice n.

// Concat 2 tuples
template<typename a, typename b, int n = 0, bool ok = (n < a::size)>
struct tuple_concat : public tuple_concat<a, b, n+1>
{
    typedef typename tuple_concat_left<
        typename element<n, a>::type,
        typename tuple_concat<a, b, n+1>::type
    >::type type;
};

template<typename a, typename b, int n>
struct tuple_concat<a, b, n, false>
{
    typedef b type;
};

就是这样! 此处的示例.

现在,对于元组特定信息:您注意到我没有使用boost :: tuple或std :: tuple.这是因为很多boost元组的实现都无法访问可变参数模板,因此使用了固定数量的模板参数(它们默认为boost::tuples::null_type).直接将其与可变参数模板一起使用是一件令人头疼的事情,因此需要另外一个抽象.

Now, for tuple specifics: you noticed I didn't used boost::tuple nor std::tuple. That is because a lot of implementations of boost tuplesdo not have access to variadic templates, so a fixed number of template parameters is used (they default to boost::tuples::null_type). Putting this directly with variadic templates is a headache, thus the need to have another abstraction.

我还假定您可以使用C ++ 11(在您的问题中使用decltype).在C ++ 03中可以连接2个元组,但重复性和无聊性更大.

I also assumed that you can use C++11 (with the decltype in your question). Concatening 2 tuples in C++03 is possible, but more repetitive and boring.

您可以非常轻松地将pack转换为元组:只需将pack定义更改为:

You can convert a pack to a tuple really easily: just change the pack definition to:

template<typename... T>
struct pack
{
    static const unsigned int size = sizeof...(T);
    typedef boost::tuple<T...> to_tuple; // < convert this pack to a boost::tuple
};

这篇关于如何从一个旧的元组和一个boost中的类型创建一个新的元组类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆