首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通用容器分配

通用容器分配
EN

Code Review用户
提问于 2015-03-06 22:08:48
回答 1查看 202关注 0票数 5

对于设置成员集合的setter,我编写模板函数以便接受任何集合类型作为输入:

代码语言:javascript
复制
class HasItems
{
public:
    template <typename C>
    void items(const C& items) {
        // Copy-and-swap omitted
        m_items.assign(std::begin(items), std::end(items));
    }

private:
    std::vector<Item> m_items;
}

但是假设Item很大,如果可能的话,我想移动它们而不是复制。此外,假设有人向我传递了一个xvalue std::vector<Item>;我可以将整个容器移到适当的位置,并完全避免接触元素!看起来是这样的:

代码语言:javascript
复制
class HasItems
{
public:
    template <typename C>
    void items(C&& items) {
        // Helper function implemented below
        assign(m_items, std::forward<C>(items));
    }

private:
    std::vector<Item> m_items;
}

// Assigns the contents of src to dest, moving as much as possible
template <typename C1, typename C2>
void assign(C1& dest, C2&& src) {
    assign(dest, std::forward<C2>(src), std::is_assignable<C1&, C2&&>{});
}

// Called if we can use operator=
template <typename C1, typename C2>
void assign(C1& dest, C2&& src, std::true_type use_equals) {
    dest = std::forward<C2>(src);
}

// Called if we must use dest.assign()
template <typename C1, typename C2>
void assign(C1& dest, C2&& src, std::false_type use_equals) {
    assign_elements(dest, std::forward<C2>(src), std::is_rvalue_reference<C2&&>{});
}

// Called if we can move the elements
template <typename C1, typename C2>
void assign_elements(C1& dest, C2&& src, std::true_type move) {
    dest.assign(std::make_move_iterator(std::begin(src)),
                std::make_move_iterator(std::end(src)));
}

// Called if we must copy the elements
template <typename C1, typename C2>
void assign_elements(C1& dest, C2&& src, std::false_type move) {
    dest.assign(std::begin(src), std::end(src));
}

这样做好吗?特别是,在std::is_rvalue_reference<C2&&>的情况下,是否有一种很好的方法来避免assign_elements()上的标记分派?(在operator=情况下,通过使用dest = std::forward<C2>(src)而不是有条件地使用std::move()避免了这种情况。)它似乎通过了我简单的单元测试集。

EN

回答 1

Code Review用户

发布于 2015-04-09 22:14:00

我已经实现了这个成语,几周后我发现了一个重要的警告:它不能很好地处理boost::iterator_range或其他集合视图。举个例子:

代码语言:javascript
复制
std::vector<std::string> dest;
std::list<std::string> src{"foo", "bar"};
// Moves elements out of src, expected
assign(dest, std::move(src));

src = {"foo", "bar"};
// Also moves elements out of src!!!
assign(dest, boost::make_iterator_range(src));

这是因为boost::make_iterator_range(src)是一个xvalue。我看不到区分“容器”(表示从xvalue移动安全)和“容器视图”(意思是移动不安全)的好方法。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/83443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档