首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >区分rvalue视图和rvalue容器

区分rvalue视图和rvalue容器
EN

Stack Overflow用户
提问于 2013-07-12 14:16:28
回答 3查看 328关注 0票数 3

我正在编写一些基于容器或可迭代的算法。基本上,我对支持for( : )风格迭代的对象进行操作(我很少直接使用for( : ),但遵循它如何查找beginend迭代器)。

std库中,大多数可迭代对象都是容器。他们都拥有自己的数据,让你看。

当一个算法通过rvalue引用获取容器时,这意味着容器的内容也是可以自由提取的。例如,如果我编写concatinate,它需要两个vectors并返回第三个,如果两个vectors都是moved,那么为了提高效率,我们需要重用第一个vector,然后使用move_iterators从第二个vector中提取数据。

但是,使用C++1Y的string_view和概念上类似的类型,我们有可迭代对象,它们不是容器,而是容器中的视图。在语义上,我相信视图的行为就像指针,因此它们的“按值”复制是将视图复制到容器中,而不是它们所引用的数据。如果我通过rvalue引用获取string_view样式视图,这并不意味着它拥有内容:移出内容是没有道理的,仅仅因为指针本身是一个rvalue,就只能移动指针的内容。

同时,容器遵循值语义,因为它们是rvalue,所以移动它们的内容是有效的。

对于string_view,这不是问题,但我已经编写了更通用的view类,比如contiguous_range_view,它允许您对vectorarrayarr[]的子集进行操作,就好像它是不可变大小的缓冲区一样。

这些视图并不总是将其内容视为const,但它们并不拥有它们的内容。因此,作为rvalue的视图并不意味着它们的内容是rvalue!

我的算法(如concatinate )在这里遇到了问题。视图与容器几乎没有区别,rvalue容器是有效的移除-从,而rvalue视图不是。通过值返回视图的函数是一个很好的模式,因为视图在语义上是指针类型。

我正在寻找一种很好的,干净的方法来区分容器和视图。是否有计划通过我现在可以模仿或挂钩的属性或标记来区分string_view中的C++1y?如果没有,是否有一个好的模式?

如果我设法阻止视图被移动-从意外,我仍然需要能够从他们有时移动,所以我需要一种方法标记一个视图是一个移动-从候选人,而不是一个rvalue引用。我怀疑make_move_range函数可以解决这个问题(这需要一个可迭代的范围,并将std::make_move_iterator应用于beginend)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-07-12 14:43:51

选项1:我认为ContainerView概念之间最明显的区别是容器有inserterase操作,而视图没有。我尝试用这个事实来编写一个类型特征来检测Container-ness。具体来说,我认为所有标准容器都有一个void erase(iterator)成员。

选项2:容器管理内存,视图不管理。标准容器都有一个成员typedef allocator_type

值得注意的是,这些观测结果都不适用于std::array或内置数组。

票数 2
EN

Stack Overflow用户

发布于 2013-07-12 14:49:20

如果目标是区分std::stringstd::string_view,我将使用如下内容:

代码语言:javascript
复制
template <
class String = std::string, 
class = typename std::enable_if<!std::is_void<decltype(std::declval<String>().substr(0))>::value>::type // Check if the type has the substr member
>
constexpr bool is_view(const String& str = String())
{
    return std::is_nothrow_constructible<String, std::string>::value;
}

作为容器,应该管理内存,它们的构造函数不抛出,而containers视图似乎有not构造函数。

编辑:多亏了Casey的回答,我认为这种用于检测类型是视图还是容器的元功能(假设视图不是简单的对象,而是数组)是可行的。

代码语言:javascript
复制
template <class Type>
constexpr bool is_view()
{
    return (!std::is_trivial<Type>::value) 
        && (!std::is_constructible<Type, 
             std::allocator<typename Type::value_type>>::value);
}
票数 1
EN

Stack Overflow用户

发布于 2013-07-12 14:33:06

也许这一总体模式会有所帮助:

代码语言:javascript
复制
struct Container
{
    CopyIterator begin() &;
    CopyIterator end() &;
    MoveIterator begin() &&;
    MoveIterator end() &&;
};

struct View
{
    CopyIterator begin();
    CopyIterator end();
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17617033

复制
相关文章

相似问题

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