【问题标题】:MPL-like vector with variadic templates: Insertion带有可变参数模板的类 MPL 向量:插入
【发布时间】:2012-03-06 12:46:20
【问题描述】:

我想知道如何使用可变参数模板编写Boost MPL-like vector_c。我已经写了下面的sn-p代码:

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&lt;1, vector&lt;1, 2, 3&gt;&gt; 返回正确的结果2。现在我的问题是:如何实现插入函数?我不使用 MPL 的原因是当我尝试它的 insert&lt;&gt; 时,它没有返回 vector_c。特别是,应该像这样应用插入:

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

其中必须产生vector&lt;1, 2, 3, 4&gt;。这可能吗?

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 不错的解决方案 - 它有助于深入了解 MPL 可以用可变参数模板重写/替换有多大。
    • 与此同时,我也得出结论,我必须编写一个push_front 函数 - 但是,我没有意识到它必须在向量本身内!我觉得在vector类之外写push_front是不可能的吧?
    • @cschwan:你当然可以(例如:ideone.com/3F4UQ)。我只是懒得这么做。
    • 感谢您的链接。当我试图在课堂之外写push_front 时,我遇到了“不完整类型的无效使用”错误。在寻找解决方案时,我找到了stackoverflow.com/questions/652155/…,其中该解决方案建议将其放入类中。这仅作为也尝试这样做的人的参考。
    【解决方案2】:

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

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

    【讨论】:

    • 感谢您的解释 - 我在哪里可以找到 as_vector
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 2020-05-22
    • 1970-01-01
    相关资源
    最近更新 更多