具有可变参数模板的MPL类矢量:插入

时间:2012-03-06 12:46:21

标签: c++ boost c++11 variadic-templates boost-mpl

我想知道如何使用可变参数模板编写Boost MPL - 类似vector_c。我已经编写了以下代码片段:

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 个答案:

答案 0 :(得分: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;
};

请注意,您需要在push_front的{​​{1}}中定义基元vector

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;
    };
};

答案 1 :(得分:1)

如果你想让MPL在插入后返回vector_c,你必须将它转换为vector_c usign as_vector。

你在这里处理半功能语言,所以如果你想要插入,你需要从旧的和索引/位置重建一个新的vector_c。 MPL做了什么,因为这样的重建非常繁琐是返回一个充当向量的类型(也就是遵循静态序列概念)并且具有重载get&lt;&gt;知道当需要位置N时,检查插入值以查看返回的内容。