当前位置: 首页 > 知识库问答 >
问题:

为什么我不能从迭代器构造一个std::跨度?

淳于泓
2023-03-14

考虑一个大型内存容器。在这个简单的例子中

std::vector v = { 0, 1, 2, 3, 4, 5 };

span允许我在内存上创建一个轻量级视图。现在,我只想打印跨度:

template<typename T>
void print(std::span<T> span) {
    std::cout << '[';
    if (span.size())
        std::copy(span.begin(), span.end() - 1, std::ostream_iterator<int>(std::cout, ", "));

    std::cout << span.back() << "]\n";
}

int main() {
    std::vector v = { 0, 1, 2, 3, 4, 5 };

    print(std::span{ v });
}

输出:

[0, 1, 2, 3, 4, 5]

现在我想制作子集(这是std::span实际上作为视图变得有用的地方)。我可以使用迭代器来指定我的范围并从std::span调用这个构造函数(3)

template< class It, class End >
explicit(extent != std::dynamic_extent)
constexpr span( It first, End last );

但这行不通:

print(std::span{ v.begin() + 2, v.end() }); //error E0289

C没有与参数列表匹配的构造函数实例参数类型为:(std::\u Vector\u iterator

有可能使用接受指针和大小的构造函数(2):

print(std::span{ v.data() + 1, 3 }); //-> prints [1, 2, 3]

但这违背了迭代器的目的。

如何使用迭代器构造std::span?我错过什么了吗?

完整代码:

#include <iostream>
#include <vector>
#include <span>
#include <algorithm>

template<typename T>
void print(std::span<T> span) {
    std::cout << '[';
    if (span.size())
        std::copy(span.begin(), span.end() - 1, std::ostream_iterator<int>(std::cout, ", "));

    std::cout << span.back() << "]\n";
}

int main() {
    std::vector v = { 0, 1, 2, 3, 4, 5 };

    print(std::span{ v.begin() + 2, v.end() });
}

在MSVC实现构造函数之前,我将使用此函数:

template<typename It>
constexpr auto make_span(It begin, It end) {
    return std::span<std::remove_pointer_t<It::pointer>>(&(*begin), std::distance(begin, end));
}

使用Visual Studio Community 2019版本16.7.5。配置:x64,发布。C语言标准= /std: c最新

共有1个答案

仉宸
2023-03-14

您可以使用迭代器构造spans,它有这样一个构造函数(由P1394添加,您可以在[views.span]中看到):

template< class It, class End >
explicit(extent != std::dynamic_extent)
constexpr span( It first, End last );

只是MSVC的标准库没有实现它。正如预期的那样,该程序在gcc上编译良好。

 类似资料:
  • 下面非常简单的代码在C 98中编译和链接时没有警告,但在C 11模式下会出现无法理解的编译错误。 标准=c 11的错误是,gcc版本4.9.0 20140302(实验)(gcc): 带clang版本3.5(trunk 202594) 我一直在看中的代码,我不明白为什么它试图实例化。 为什么在C 11中需要复制构造函数std::pair? 注:上述代码是从不可复制映射的映射迭代器上不支持的等式运算符

  • 我想为客户数据结构提供一个视图,它有自己的迭代器。我编写了一个小程序来测试它,如下所示。如果我取消对begin()的注释,它就会工作。但是如果我使用DummyIter,那么我会得到一个编译错误。 在我的完整程序中,我实现了一个完整的迭代器,但为了简单起见,我把它缩小到了必要的函数。 我使用的是GCC 11.1.0。我在迭代器中缺少了什么使其符合范围?

  • 在MS Visual Studio 2013中使用C 11,我有一个类testNetInfo,它有一个来自std::字符串的非显式构造函数,我想从std::初始化器字符串列表构造这些向量。 如果我从initializer_list构造一个临时向量,我可以用它来设置真正的向量: 但尝试直接从initList创建netInfo时,如下所示:

  • 伊登 JLS所说的是: 设C是ClassName表示的类。设n是一个整数,使得C是类的第n个词汇封闭类,在该类中出现有条件的this表达式。 [...] 如果当前类不是类C或C本身的内部类,则为编译时错误。 在的情况下,内部类集。这意味着上面的代码应该可以正常工作。发生了什么?

  • 我遇到了一个有趣的问题,我不明白发生了什么: 据我所知,我提供的单个整数参数可以解释为使用参数调用构造函数,也可以解释为使用初始化列表的构造函数。似乎只有当我提供左值时才调用initialiser_list构造函数,但当我提供r-value(至少是文字)时,构造函数。为什么会这样? 这也意味着: 结果仅为大小为1的向量; 结果是一个大小为num\u元素的向量,但我认为应该避免这种初始化,因为偶尔会

  • 我正在尝试创建一个文本区域,在这里我可以添加HTML元素,这些元素应该可以在字符级别上拖动。这个问题与我目前正在问的另一个问题有关,但与GWT有关。为了创建这样一个文本区域,我试图了解如何一步一步地完成它。到目前为止,我得到的是: JSFIDLE JavaScript: 超文本标记语言: 但是出于某种原因,我只能拖动。我真正需要的是能够拖动一个或者更好的一个... 我怎样才能做到这一点? PS:如