2013-07-11 64 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

相关问题