![](/img/trans.png)
[英]How to create a boost::tuple with the specified number of elements (of the same type)?
[英]How to create a new tuple type from an old one and a type in boost?
我有一個元組類型。 我想在其中添加元素類型以獲得新的元組類型。 我可以這樣做
decltype tuple_cat(MyTuple, std::tuple<MyType>())
但是,我在boost::tuple
找不到tuple_cat
,如何在boost中做到這一點?
我假設你在編譯時想要這一切。
以下是一般性解釋:連接元組類似於連接列表或數組,是算法是相同的。 在這里,給出元組a
和b
,我選用到的最后一個元素移動a
到年初b
,並且重復,直到a
是空的。
第一:基礎結構。 以下結構保留參數包。 它可以是任何東西,例如元組:
template<typename... T>
struct pack
{
static const unsigned int size = sizeof...(T);
};
請注意,包的大小存儲在其中。 它不是強制性的,但它便於解釋。 Boost使用struct boost::tuples::length<T>::value
(更詳細)。
要訪問第i個位置的元素,我們使用類似於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;
};
現在,我們必須使用一個低級操作,即將一個元素添加到包的一側(在左側或右側添加)。 這里添加了左邊的選項,但它不是唯一的選擇:
// 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
不會更改,而是使用indice來知道要添加的元素。 繼承定義了一個'type'typedef,它是n
和另一個元組之后所有索引的串聯(不包括n
,按順序)。 我們只需要在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 tuples的實現都無法訪問可變參數模板,所以使用了固定數量的模板參數(默認為boost::tuples::null_type
)。 直接使用可變參數模板是一件令人頭疼的事情,因此需要另外一個抽象。
我還假設您可以使用C ++ 11(在您的問題中使用decltype
)。 在C ++ 03中連接2個元組是可能的,但更重復和無聊。
您可以非常輕松地將pack
轉換為元組:只需將pack
定義更改為:
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
};
C ++ 14提供了一個庫,用於在編譯類型中生成一個整數序列。 這有助於操作靜態序列,如元組和數組( 示例 )。 可以獲得整數序列
template<size_t... Ints>
struct integer_sequence {};
template<size_t Size, size_t... Ints>
struct implementation : implementation<Size-1, Size-1, Ints...> {};
template<size_t... Ints>
struct implementation<0, Ints...>
{
typedef integer_sequence<Ints...> type;
};
template<class... T>
using index_sequence_for = typename implementation<sizeof...(T)>::type;
要連接MyTuple
和MyType
您可以編寫簡單的函數:
template<typename X, typename Tuple, size_t... Ints>
auto concat(X x, Tuple t, integer_sequence<Ints...>)
-> decltype( std::make_tuple(x, std::get<Ints>(t)...) )
{
return std::make_tuple(x, std::get<Ints>(t)...);
}
template<typename X, typename... T>
std::tuple<X, T...> concat(X x, std::tuple<T...> t)
{
return concat(x, t, index_sequence_for<T...>());
}
concat(MyType, MyTuple);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.