你能将 int*[N] 转换为 std::span<const int * const> 吗?

问题描述 投票:0回答:1

我有以下代码:

#include <span>

int* pointers[3];
std::span<const int* const> s = pointers;

GCC 接受这一点,但 Clang(编译 libstdc++)拒绝它,并指出:

<source>:4:29: error: no viable conversion from 'int *[3]' to 'std::span<const int *const>'
    4 | std::span<const int* const> s = pointers;
      |                             ^   ~~~~~~~~
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/span:230:7: note: candidate constructor not viable: no known conversion from 'int *[3]' to 'const span<const int *const> &' for 1st argument
  230 |       span(const span&) noexcept = default;
      |       ^    ~~~~~~~~~~~
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/span:192:2: note: candidate template ignored: could not match 'const int *' against 'int *'
  192 |         span(type_identity_t<element_type> (&__arr)[_ArrayExtent]) noexcept
      |         ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/span:199:2: note: candidate template ignored: could not match 'array<_Tp, _ArrayExtent>' against 'int *[3]'
  199 |         span(array<_Tp, _ArrayExtent>& __arr) noexcept
      |         ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/span:206:2: note: candidate template ignored: could not match 'array<_Tp, _ArrayExtent>' against 'int *[3]'
  206 |         span(const array<_Tp, _ArrayExtent>& __arr) noexcept
      |         ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/span:218:2: note: candidate template ignored: constraints not satisfied [with _Range = int *(&)[3]]
  218 |         span(_Range&& __range)
      |         ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/span:213:8: note: because '!is_array_v<remove_cvref_t<int *(&)[3]> >' evaluated to false
  213 |           && (!is_array_v<remove_cvref_t<_Range>>)
      |               ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/span:238:2: note: candidate template ignored: could not match 'span<_OType, _OExtent>' against 'int *[3]'
  238 |         span(const span<_OType, _OExtent>& __s) noexcept
      |         ^

请参阅编译器资源管理器

我的印象是,如果只需要限定转换(例如

std::span
int*
),则可以从范围构造
const int * const
,那么这里哪个编译器是正确的?

这很可能只是 Clang/GCC 互操作性的怪癖,考虑到代码也使用

-stdlib=libc++
进行编译。

c++ clang c++23 compiler-bug std-span
1个回答
0
投票

std::span<const X>
没有采用
X[N]
C 数组引用的构造函数(从 c++26 开始)。

所以在这种情况下你必须手动构建跨度:

span<const int* const> s{ pointers, 3 };

是的,这有点痛苦,并且使用

std::array
代替 C 数组并没有多大帮助,出于同样的原因(但是
std::array
总是比 c 数组更好)。

还有,如果有一个

span::operator< span<const T> >
就好了...

© www.soinside.com 2019 - 2024. All rights reserved.