2012-02-03 76 views
2

如何轉變這種類型:變換元組「三角」的元組

std::tuple<T0, T1, ..., TN1, TN> 

到這一點:

std::tuple< 
    std::function<T0()>, 
    std::function<T1(T0)>, 
    std::function<T2(T0, T1)>, 
    ... 
    std::function<TN(T0, ..., TN1)> 
> 
+0

創建一個「廣場」的元組[竟然是微不足道的(http://stackoverflow.com/questions/9123712/transform-tuple-type/),但我想這其中的確涉及計數,尤其是因爲我想在_first_ n個元素,所以只使用一個'<頭,尾...>'結構是不夠的...... – pascal 2012-02-03 17:07:40

回答

4

...是不夠的,但是你總是可以使用模式匹配(即部分專業化)與遞歸:

#include <tuple> 
#include <functional> 
#include <cstdlib> 

// A type to store list of integers 
template <size_t... ns> 
struct integers 
{ 
    template <size_t n> 
    using push_back = integers<ns..., n>; 
}; 

// This generates 'integers<0, 1, 2, ..., n-1>' 
template <size_t n> 
struct iota 
{ 
    typedef typename iota<n-1>::type::template push_back<n-1> type; 
}; 
template <> 
struct iota<0> 
{ 
    typedef integers<> type; 
}; 

// Put a type to the front of the argument list 
template <typename T, typename U> 
struct push_front; 
template <typename T, typename R, typename... A> 
struct push_front<R(A...), T> 
{ 
    typedef R type(T, A...); 
}; 

// This converts 'std::tuple<T0, T1, ..., TN>' to the function type 
// 'TK(T0, T1, ..., TK-1)' where K is the first parameter 
template <size_t, typename...> 
struct slice; 
template <size_t end, typename First, typename... Rest> 
struct slice<end, First, Rest...> 
{ 
    typedef typename push_front<typename slice<end-1, Rest...>::type, First>::type type; 
}; 
template <typename First, typename... Rest> 
struct slice<0, First, Rest...> 
{ 
    typedef First type(); 
}; 

// This calls 'slice' on T... for all integers in the list. 
template <typename T, typename U> 
struct triangularize_impl; 
template <typename... T, size_t... n> 
struct triangularize_impl<std::tuple<T...>, integers<n...>> 
{ 
    typedef std::tuple<std::function<typename slice<n, T...>::type>...> type; 
}; 

// This is a wrapper of 'triangularize_impl'. 
template <typename T> 
struct triangularize; 
template <typename... T> 
struct triangularize<std::tuple<T...>> 
{ 
    typedef typename triangularize_impl<std::tuple<T...>, typename iota<sizeof...(T)>::type>::type type; 
}; 

作爲一個演示,在g ++ 4.7當我們寫

triangularize<std::tuple<int, float, double, char>>::type d = 0; 

錯誤消息顯示

error: conversion from ‘int’ to non-scalar type 
     ‘triangularize<std::tuple<int, float, double, char> >::type {aka 
     std::tuple<std::function<int()>, 
        std::function<float(int)>, 
        std::function<double(int, float)>, 
        std::function<char(int, float, double)> >}’ 
     requested 

顯示的代碼是正確的。

+0

在G ++ 4.6.1我得到「錯誤:預期不合格-ID使用前」在整數::的push_back [因爲它太舊了](http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51139),但它適用於'template struct integers_push_back; template struct integers_push_back <整數,n> { \t typedef整數類型; };'和'integers_push_back < \t \t類型名稱絲毫 ::類型, \t \t N - 1 \t> ::類型;'代替'IOTA ::類型::模板的push_back '。 – pascal 2012-02-03 23:48:27

+0

@pascal是g ++ - 4.6不支持別名模板。 – kennytm 2012-02-04 03:18:37