7

我尝试了一个小例子来习惯 GSL 和 range-v3 库,我想知道它们如何协同工作。我有这个玩具例子

#include <iostream>
#include <range/v3/all.hpp>

using namespace std;
using namespace ranges;

void example_vector(vector<int> const& v)
{
  ranges::for_each(view::tail(v), [](int x){
    cout << x << ' ';
  });
  cout << '\n';
}

int main()
{
   auto seq = vector<int> { 2,2,2,0,0,2,1,2 };
   example_vector(seq);
}

哪个有效。但是,如果我尝试将gsl::span<int>其用作范围,则会导致错误消息。编译器告诉我这span并不能满足视图概念。

#include <gsl.h>

// ...

void example_span(gsl::span<const int> v)
{
  ranges::for_each(view::tail(v), [](int x){
    cout << x << ' ';
  });
  cout << '\n';
}

编译器消息:

note: candidate template ignored: disabled by 'enable_if'
      [with Rng = gsl::span<const int, -1> &, Rest = <>, _concept_requires_123 = 42]
                    CONCEPT_REQUIRES_(ViewConcept<Rng, Rest...>())>

但据我了解,它应该是因为 aspan 一个特定的视图,甚至具有begin()end()迭代器(相同类型)。

  • 如果他们一起工作是可组合的,或者有什么理由不兼容,那不是很酷吗?
  • 我认为这是一个来自 range-v3 中强大的“概念”使用的问题。如果该语言支持某种其他类型的概念功能,它会自动解决吗?
  • span如果我想在某些(非工业)软件中同时使用这两个库,我认为目前需要一些调整。我应该改变什么才能使这些协同工作?(如果这是个好主意的话)
  • 这也最终使我想到了“有什么课程可以完成工作range-v3?”的问题。从外观、适配器或此类继承是当前告诉编译器这些概念要求的唯一方法吗?
4

1 回答 1

9

range-v3 中的View概念(以及范围 TS,就此而言)需要一个类型R来满足Range概念 -begin(r)end(r)界定迭代器范围 - 并且Semiregular概念 -R必须是可复制/移动可构造的复制/移动可分配的,并且默认可构造。Rangea (whatbegin和return)的迭代器和哨兵类型end也必须是Semiregular(以及其他要求)。

span族不满足这个View概念,因为spans 在某些情况下不是默认可构造的,并且它们的迭代器在任何情况下都不是默认可构造的。由于即使是标准 C++ 也需要前向迭代器的默认构造,所以当前的span迭代器既不符合 Ranges TS、range-v3 也不符合标准 C++。

也就是说,满足所有这些要求系列所需的更改是最小且直接的

20161207 更新:

range-v3 现在包含一个span可以正确建模View/Range概念的实现。

20170128 更新:

gsl::span现在有默认的可构造迭代器。因此,跨度现在可与 range-v3 一起使用。具有动态范围(例如gsl::span<int>)的跨度模型是Range&View概念,具有静态范围(例如gsl::span<int, 42>)模型的跨度仅Range因为它们不满足View默认构造的要求。

于 2016-03-29T07:25:52.277 回答