2013-07-11 100 views
2

例如,我有類型如何基於一些派生類型創建一個元組?

template<unsigned i> struct Element; 

template struct Element<0> {typedef int Type}; 
template struct Element<1> {typedef float Type}; 
template struct Element<2> {typedef double Type}; 

static const int COUNT = 3; 

,並希望進行類型的元組作爲

std::tuple<Element<0>::Type, Element<1>::Type, Element<2>::Type> 

怎麼辦呢,如果計數是恆定的,但並不總是3?

+0

您使用的是什麼C++版本? – CookieOfFortune

+0

MSVC 2012 v110,但我也可以使用v120_CTP_Nov2012。 – user1899020

+0

有一個包,比如'unsigned ...'? –

回答

2

基本上有兩種方法,它們只有不同的概念:Indices(當你有(功能)可變參數模板可用時),或者當你走時(當你有Visual C++時)手動構建元組。

指數:

template<unsigned... Is> struct seq{}; 
template<unsigned I, unsigned... Is> 
struct gen_seq : gen_seq<I-1, I-1, Is...>{}; 
template<unsigned... Is> 
struct gen_seq<0, Is...>{ using type = seq<Is...>; }; 

template<unsigned N, template<unsigned> class TT, 
    class Seq = typename gen_seq<N>::type> 
struct tuple_over{}; 

template<unsigned N, template<unsigned> class TT, unsigned... Is> 
struct tuple_over<N, TT, seq<Is...>>{ 
    using type = std::tuple<typename TT<Is>::type...>; 
}; 

手冊遞歸:

template<unsigned N, template<unsigned> class TT, class TupleAcc = std::tuple<>> 
struct tuple_over{ 
    using tt_type = typename TT<N-1>::type; 
    // since we're going from high to low index, 
    // prepend the new type, so the order is correct 
    using cat_type = decltype(std::tuple_cat(std::declval<std::tuple<tt_type>>(), std::declval<TupleAcc>())); 
    using type = typename tuple_over<N-1, TT, cat_type>::type; 
}; 

template<template<unsigned> class TT, class Tuple> 
struct tuple_over<0, TT, Tuple>{ using type = Tuple; } 

用法是兩個版本的相同:

using result = tuple_over<COUNT, Element>::type; 

Live example for indices.
Live example for manual recursion.

+2

請注意,只要您使用'typedef'替換'使用'別名,手動遞歸版本就可以在VS2012上運行。 – Xeo

2

這是一種可能的方法。鑑於你的類模板定義:

template<unsigned i> struct Element; 

template<> struct Element<0> { typedef int type; }; 
template<> struct Element<1> { typedef float type; }; 
template<> struct Element<2> { typedef double type; }; 

您可以利用通常的指標框架編寫這樣的事:

#include <tuple> 

namespace detail 
{ 
    template<int... Is> 
    struct seq { }; 

    template<int N, int... Is> 
    struct gen_seq : gen_seq<N - 1, N - 1, Is...> { }; 

    template<int... Is> 
    struct gen_seq<0, Is...> : seq<Is...> { }; 

    template<template<unsigned int> class TT, int... Is> 
    std::tuple<typename TT<Is>::type...> make_tuple_over(seq<Is...>); 
} 

template<template<unsigned int> class TT, int N> 
using MakeTupleOver = 
    decltype(detail::make_tuple_over<TT>(detail::gen_seq<N>())); 

這是你將如何使用它在你的程序:

#include <type_traits> // For std::is_same 

int main() 
{ 
    static_assert(
     std::is_same< 
      MakeTupleOver<Element, 3>, 
      std::tuple<int, float, double> 
     >::value, "!"); 
} 

這是live example

相關問題