【问题标题】:How to make class compatible with std::span constructor that takes a range?如何使类与采用范围的 std::span 构造函数兼容?
【发布时间】:2021-11-16 11:04:47
【问题描述】:

我希望能够将我的自定义容器传递给这个 std::span 构造函数:

template< class R >
explicit(extent != std::dynamic_extent)
constexpr span( R&& range );

我需要向我的自定义类添加什么以使其满足能够将其传递给接收范围的std::span 构造函数的要求?

例如,使用std::vector,我们可以这样做:

std::vector<int> v = {1, 2, 3};
auto span = std::span{v};

我已经将这些添加到我的自定义类中:

Type* begin()
{
    return m_Data;
}

Type* end()
{
    return m_Data + m_Length;
}

const Type* data() const
{
    return m_Data;
}

size_t size() const
{
    return m_Length;
}

...这反过来又允许我使用基于范围的循环,以及std::data(my_container)std::size(my_container)。我错过了什么,以便我也可以将我的容器传递给 std::span 构造函数?是否需要实现更复杂的迭代器?

【问题讨论】:

  • 请提供minimal reproducible example,其中包括您的整个类型。有问题的 span 构造函数也列出了它的约束。你检查了吗?
  • 我确实看过约束,但我对理解它们感到困惑。

标签: c++ c++20 std-ranges std-span


【解决方案1】:

这是因为你的Container不满足contiguous_range,定义为:

template<class T>
  concept contiguous_­range =
    random_­access_­range<T> && contiguous_­iterator<iterator_t<T>> &&
    requires(T& t) {
      { ranges::data(t) } -> same_­as<add_pointer_t<range_reference_t<T>>>;
    };

requires子句中ranges::data(t)的返回类型为const Type*,与add_pointer_t&lt;range_reference_t&lt;T&gt;&gt;的返回类型为Type*不同。

解决方法是将非const data() 添加到您的Container 中,返回Type*

Type* data()  { return m_Data; }

【讨论】:

  • 确实这是我的问题。这是否意味着 std 容器同时实现了 const 和非 const 版本?我想是的。
  • @Deathicon。不必要。以string_view为例,它只有一个data() const返回const char*,但由于它也只有一个begin() constend() const返回const char*,这也使它成为contiguous_range的模型。
猜你喜欢
  • 1970-01-01
  • 2019-12-18
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 1970-01-01
  • 2018-12-14
  • 1970-01-01
  • 2014-07-28
相关资源
最近更新 更多