std::span 迭代器能否比创建它们的 span 对象更长寿?
Can std::span iterators outlive the span object they are created from?
换句话说,反过来说,std::span
迭代器在 span 实例被销毁后是否失效?
我有一个矢量需要用不同的布局进行迭代。我正在尝试使用 std::span
来避免编写大量迭代器样板文件或引入外部库依赖项。简化示例:
#include <iostream>
#include <span>
#include <vector>
template <size_t N>
struct my_view {
std::vector<int> vec;
auto as_span() {
return std::span<int[N]>((int(*)[N])vec.data(), vec.size() / N);
}
auto begin() {
return as_span().begin();
}
auto end() {
return as_span().end();
}
};
int main() {
std::vector vec {1, 2, 3, 4, 5, 6};
my_view<2> pairs {std::move(vec)};
for (auto pair : pairs) {
std::cout << pair[0] << " " << pair[1] << std::endl;
}
my_view<3> triplets {std::move(pairs.vec)};
for (auto triplet : triplets) {
std::cout << triplet[0] << " " << triplet[1] << " " << triplet[2] << std::endl;
}
return 0;
}
我很欣赏这个问题连续问同一个问题的正面和负面版本。因此...
Can std::span
iterators outlive the span object they are created from?
是的。
Are std::span
iterators invalidated after the span instance is destroyed?
没有
这就是为什么您在 [span.syn] 中看到:
template<class ElementType, size_t Extent>
inline constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true;
哪里,从[range.range]/5:
Given an expression E
such that decltype((E))
is T
, T
models borrowed_range
only if the validity of iterators obtained from the object denoted by E
is not tied to the lifetime of that object.
[Note 2: Since the validity of iterators is not tied to the lifetime of an object whose type models borrowed_range
, a function can accept arguments of such a type by value and return iterators obtained from it without danger of dangling. — end note]
如果 span
的迭代器绑定到 span
的生命周期,这样做是无效的——span
必须是非借用的(例如,vector<T>
显然不是借来的)。
gsl::span
的迭代器用于保留指向 span
的指针(这显然会导致迭代器失效),但已更改为 in Feb 2020(我没有查看评论以找到那里的讨论,但那个符合标准行为)。
换句话说,反过来说,std::span
迭代器在 span 实例被销毁后是否失效?
我有一个矢量需要用不同的布局进行迭代。我正在尝试使用 std::span
来避免编写大量迭代器样板文件或引入外部库依赖项。简化示例:
#include <iostream>
#include <span>
#include <vector>
template <size_t N>
struct my_view {
std::vector<int> vec;
auto as_span() {
return std::span<int[N]>((int(*)[N])vec.data(), vec.size() / N);
}
auto begin() {
return as_span().begin();
}
auto end() {
return as_span().end();
}
};
int main() {
std::vector vec {1, 2, 3, 4, 5, 6};
my_view<2> pairs {std::move(vec)};
for (auto pair : pairs) {
std::cout << pair[0] << " " << pair[1] << std::endl;
}
my_view<3> triplets {std::move(pairs.vec)};
for (auto triplet : triplets) {
std::cout << triplet[0] << " " << triplet[1] << " " << triplet[2] << std::endl;
}
return 0;
}
我很欣赏这个问题连续问同一个问题的正面和负面版本。因此...
Can
std::span
iterators outlive the span object they are created from?
是的。
Are
std::span
iterators invalidated after the span instance is destroyed?
没有
这就是为什么您在 [span.syn] 中看到:
template<class ElementType, size_t Extent>
inline constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true;
哪里,从[range.range]/5:
Given an expression
E
such thatdecltype((E))
isT
,T
modelsborrowed_range
only if the validity of iterators obtained from the object denoted byE
is not tied to the lifetime of that object.
[Note 2: Since the validity of iterators is not tied to the lifetime of an object whose type models
borrowed_range
, a function can accept arguments of such a type by value and return iterators obtained from it without danger of dangling. — end note]
如果 span
的迭代器绑定到 span
的生命周期,这样做是无效的——span
必须是非借用的(例如,vector<T>
显然不是借来的)。
gsl::span
的迭代器用于保留指向 span
的指针(这显然会导致迭代器失效),但已更改为 in Feb 2020(我没有查看评论以找到那里的讨论,但那个符合标准行为)。