提问人:Jan Schultke 提问时间:6/23/2023 最后编辑:Jan Schultke 更新时间:9/13/2023 访问量:132
无法从临时 std::array<int 构造 std::span<int>>
Can't construct std::span<int> from temporary std::array<int>
问:
我有以下代码,我希望它能工作,但它没有:
#include <array>
#include <span>
void foo(std::span<int>);
int main() {
foo(std::array<int, 3>{});
}
clang 无法编译以下内容:
<source>:7:5: error: no matching function for call to 'foo'
7 | foo(std::array<int, 3>{});
| ^~~
<source>:4:6: note: candidate function not viable: no known conversion from 'std::array<int, 3>' to 'std::span<int>' for 1st argument
4 | void foo(std::span<int>);
| ^ ~~~~~~~~~~~~~~
我希望这会调用构造函数:
template< class U, std::size_t N > constexpr span( const std::array<U, N>& arr ) noexcept; // (6)
4-6) 构造一个跨度,该跨度是数组 arr 的视图;生成的跨度为 和 。
size() == N
data() == std::data(arr)
仅当 is 且从 to 的转换最多是限定转换时,这些重载才会参与重载解析。
extent == std::dynamic_extent || N == extent
true
std::remove_pointer_t<decltype(data(arr))>
element_type
请参阅 cppreference 上的 std::span::span
为什么不满足此构造函数的约束?
extent == std::dynamic_extent
对于 ,因此显然满足了第一个要求std::span<int>
std::remove_pointer_t<decltype(data(arr))>
是 ,等于 ,因此也满足第二个要求int
std::span<int>::element_type = int
我看不出有什么理由我不能调用这个构造函数。
答:
2赞
Artyer
6/23/2023
#1
资格转换只能使某些东西更合格。
decltype(data(arr))
用于 . 无法通过资格转换进行转换。const int*
const std::array<int, 3>&
const int
int
std::span<const int>(std::array<int, 3>{})
但是确实有效 ( -> )。const int
const int
评论
0赞
Jan Schultke
6/23/2023
那么,从临时数组构造一个最简短的方法是什么,或者没有单行代码呢?std::span
0赞
Artyer
6/23/2023
@JanSchultke 是获取临时值的非常量值的好方法。所以,或者如果你想要那个班轮。但是,在一组非常特定的情况下,这没有用,因为阵列会立即死亡。为什么不直接使用(隐式转换为跨度)?auto& unmove(auto&& temporary) { return temporary; }
std::span<int>(unmove(std::array<int, 3>{}))
std::span<int>([](auto&& arr)->auto&{return arr;}(std::array<int, 3>{}))
auto f = std::array<int, 3>{}
0赞
Jan Schultke
6/23/2023
它应该演示如何避免模板参数包,转而使用 、 、 等。std::span
std::initializer_list
std::array
0赞
Artyer
6/23/2023
std::initializer_list
也是 const,因此您可能正在寻找 const span。也许还有两个重载:void f(std::span<const int>); inline void f(std::initializer_list<int> ilist) { f(std::span{ilist}); }
0赞
Jan Schultke
6/23/2023
实际上,我一直在寻找相反的情况,因为我想从跨度中移动,而 a or not 真的让你这样做std::initializer_list
std::span<const>
评论