0

我想知道如何使用可变参数模板编写类似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>。_ 这可能吗?

4

2 回答 2

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在两个vector's 中定义原语:

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;
    };
};
于 2012-03-06T20:35:33.690 回答
1

如果您希望 MPL 在插入后返回 vector_c,则必须将其转换为 vector_c 并使用 as_vector。

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

于 2012-03-06T20:00:52.467 回答