2012-03-06 66 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