C++20 std::span:转换构造函数的用法

rryofs0p  于 2023-07-01  发布在  其他
关注(0)|答案(1)|浏览(90)

C++ std::span的转换构造函数的形式为:

template<class OtherElementType, size_t OtherExtent>
  constexpr explicit(see below) span(
     const span<OtherElementType, OtherExtent>& s) noexcept;

带约束的,可用于以下目的:

int arr[]{1, 2, 3};

span<int, 3> sf{arr};
// static span to dynamic span.
span<int> sd{sf};

// non-const to const span.
span<const int> scd{sd};
span<const int, 3> sfc{sf};

// dynamic to static span.
span<int, 3> sf2{sd};

这个构造函数还有哪些其他用途可以满足这个约束?
is_­convertible_­v<OtherElementType(*)[], element_­type(*)[]>是真的。[注意:目的是只允许OtherElementTypeelement_­type的限定转换。- 尾注]

pxyaymoc

pxyaymoc1#

目的是允许在span之间进行隐式转换,只要此转换是限定转换并且大小匹配。它也可以用于像你的例子中那样的显式转换,但是(8)是特殊的,因为它只在少数情况下是explicit。例如:

void process_all(std::span<const int> numbers);

std::span<int> get_range();

void foo() {
    auto r = get_range(); // ok, sizes match and qualifying conversion takes place
    process_all(r);
}

这是可能的,因为有一个从intconst int的限定转换,所以我们可以将std::span<int>转换为std::span<const int>。这种用例非常常见,因为生成const std::span<T>并不能确保元素的不变性,只有std::span<const T>才能做到这一点。
该限定转换实际上可以是多个级别深度的,例如我们可以:

  • std::span<const int * const * const>为函数参数
  • std::span<int**>传递给它

然而,这不是这个构造函数的唯一属性,(7)也是如此。你可能会问:为什么我们不直接使用constructor(7)?“*

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

此构造函数适用于任何大小的连续范围,而span是一个。但是,对于静态范围,它总是显式的,并且只有构造函数(8)允许在大小相等的静态范围之间进行隐式转换。例如:

#include <span>

void process_all(std::span<const int, 100> numbers);

std::span<int, 100> get_range();
std::span<int, 10> get_short_range();
std::span<int> get_dynamic_range();

void foo() {
    process_all(get_range());         // OK
    process_all(get_short_range());   // ill-formed, need explicit conversion
    process_all(get_dynamic_range()); // ill-formed, need explicit conversion
}

你给出的例子都使用了显式转换,所以它们没有说明(8)的特殊之处,即它在比其他构造函数更少的情况下是有条件显式的。

相关问题