簡體   English   中英

如何從舊的元組類型和boost類型創建新的元組類型?

[英]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中做到這一點?

我假設你在編譯時想要這一切。

以下是一般性解釋:連接元組類似於連接列表或數組,是算法是相同的。 在這里,給出元組ab ,我選用到的最后一個元素移動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;

要連接MyTupleMyType您可以編寫簡單的函數:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM