2012-03-06 77 views
0

我想知道如何使用可變參數模板來編寫類似Boost MPL的vector_c。我已經寫了下面的代碼片段:MPL-like vector with variadic templates:Insertion

template <std::size_t element, std::size_t ... E> 
struct vector 
{ 
    typedef vector<E ...> next; 

    static constexpr std::size_t size() 
    { 
     return sizeof... (E); 
    } 

    static constexpr std::size_t value() 
    { 
     return element; 
    } 
}; 

template <std::size_t element> 
struct vector<element> 
{ 
    // no need to define 'next' here 

    static constexpr std::size_t size() 
    { 
     return 1; 
    } 

    static constexpr std::size_t value() 
    { 
     return element; 
    } 
}; 

您可能注意到,vector必須在其中至少有一個元素,但是這是不是真的對我的限制。與上面的定義,它是很容易寫「功能」,用於訪問一個給定索引的元素:

template <std::size_t index, typename T> 
struct get 
{ 
    typedef typename get<index - 1, typename T::next>::type type; 
}; 

template <typename T> 
struct get<0, T> 
{ 
    typedef T type; 
}; 

例如,get<1, vector<1, 2, 3>>返回正確的結果2。現在我的問題:如何實現插入功能?我不使用MPL的原因是,當我嘗試它的insert<>時,它沒有返回vector_c。特別地,插入應適用這樣的:

insert<vector<1, 3, 4>, 1, 2>::type 
// ^   ^^ 
//  type   at element 

其中必須收率vector<1, 2, 3, 4>。那可能嗎?

回答

2

在Haskell而言,

insert list 0 element = element : list 
insert list at element = (head list) : insert (tail list) (at-1) element 

和翻譯這個C++模板:

// insert list at element = 
template <typename List, size_t at, size_t element> 
struct Insert 
{ 
    typedef typename 
     // insert (tail list) (at-1) element 
     Insert<typename List::next, at-1, element>::type:: 
     // (head list) : … 
     template push_front<List::value()>::type 
    type; 
}; 

// insert list 0 element = 
template <typename List, size_t element> 
struct Insert<List, 0, element> 
{ 
    // element : list 
    typedef typename List::template push_front<element>::type type; 
}; 

請注意,您需要在這兩個vector的定義原始push_front

template <std::size_t element, std::size_t ... E> 
struct vector<element, E...> 
{ 
    template <size_t x> 
    struct push_front 
    { 
     typedef vector<x, element, E...> type; 
    }; 
}; 
+0

不錯的解決方案 - 它有助於瞭解如何大量提升MPL可以重寫或用可變參數模板取代。 – mark 2012-03-06 21:05:33

+0

與此同時,我也得出結論,我必須寫一個'push_front'函數 - 但是,我沒有意識到它必須位於vector本身內部!我認爲在矢量類之外編寫push_front是不可能的,對吧? – cschwan 2012-03-07 09:47:35

+1

@cschwan:當然你*可以*(例如:http://ideone.com/3F4UQ)。我只是不打算這麼做。 – kennytm 2012-03-07 10:08:32

1

如果你希望MPL在插入後返回vector_c,你必須將它指定爲vector_c usign as_vector。

你正在處理一個半函數語言,所以如果你想插入,你需要重建一個新的vector_c從舊的索引/位置。 MPL做了什麼,因爲這樣的重構是非常乏味的,因爲返回一個類型作爲一個向量(又名遵循靜態序列概念),並且有一個過載得知當需要位置N時,檢查插入值以查看回報什麼。

+0

感謝您的解釋 - 我在哪裏可以找到'as_vector'? – cschwan 2012-03-07 09:48:54