You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apple Clang下使用迭代器对构造std::span失败的编译问题

Apple Clang 环境下迭代器构造std::span编译失败问题

问题背景

实现函数时通过const引用接收level_state类型对象,该对象包含std::vector<unsigned short>类型的成员floor_datas,需要为该vector的指定范围构造std::span<const unsigned short>。代码在多数新版本编译器环境下可正常编译,但在Apple Clang搭配macOS 12.3及更早版本SDK的libc++环境下编译报错。

复现代码

#include <span>
#include <vector>
#include <cstddef>
struct level_state {
    std::vector<unsigned short> floor_datas;
};

struct room_info {
    std::vector<std::size_t> floor;
};

unsigned short get_floor_data_count(const unsigned short header) {
    return header & 0x3FFF;
}

std::span<const unsigned short> get_floor_data(const level_state& level, const room_info& room, const std::size_t sector_offset) {
    const std::size_t offset = room.floor[sector_offset];
    const auto header = level.floor_datas[offset];
    auto span = std::span(level.floor_datas.begin() + offset, level.floor_datas.begin() + offset + get_floor_data_count(header));
    //assert_postcondition(((*(span.rbegin())) & 0x3FF) == 0x3FF, "Floor Data does not end with 0x3FFF");
    return span;
}

编译报错信息

[build] /.../floor_data.cpp:229:64: error: no matching constructor for initialization of 'std::span<const unsigned short, std::dynamic_extent>'
[build]                         std::span<const unsigned short, std::dynamic_extent> span = std::span<const unsigned short, std::dynamic_extent>(level.floor_datas.begin() + offset,
[build]                                                                                     ^                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/span:405:41: note: candidate constructor not viable: no known conversion from 'std::__wrap_iter<const unsigned short *>' to 'std::span<const unsigned short, 18446744073709551615>::pointer' (aka 'const unsigned short *') for 1st argument
[build]     _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, size_type __count) : __data{__ptr}, __size{__count} {}
[build]                                         ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/span:406:41: note: candidate constructor not viable: no known conversion from 'std::__wrap_iter<const unsigned short *>' to 'std::span<const unsigned short, 18446744073709551615>::pointer' (aka 'const unsigned short *') for 1st argument
[build]     _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{static_cast<size_t>(distance(__f, __l))} {}
[build]                                         ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/span:424:19: note: candidate template ignored: requirement '__is_span_compatible_container<std::__wrap_iter<const unsigned short *>, const unsigned short, void>::value' was not satisfied [with _Container = std::__wrap_iter<const unsigned short *>]
[build]         constexpr span(      _Container& __c,
[build]                   ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/span:430:19: note: candidate template ignored: requirement '__is_span_compatible_container<const std::__wrap_iter<const unsigned short *>, const unsigned short, void>::value' was not satisfied [with _Container = std::__wrap_iter<const unsigned short *>]
[build]         constexpr span(const _Container& __c,
[build]                   ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/span:437:19: note: candidate template ignored: could not match 'span' against '__wrap_iter'
[build]         constexpr span(const span<_OtherElementType, _OtherExtent>& __other,
[build]                   ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/span:402:15: note: candidate constructor not viable: requires 1 argument, but 2 were provided
[build]     constexpr span           (const span&) noexcept = default;
[build]               ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/span:410:15: note: candidate template not viable: requires single argument '__arr', but 2 arguments were provided
[build]     constexpr span(element_type (&__arr)[_Sz])          noexcept : __data{__arr}, __size{_Sz} {}
[build]               ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/span:415:15: note: candidate template not viable: requires single argument '__arr', but 2 arguments were provided
[build]     constexpr span(array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
[build]               ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/span:420:15: note: candidate template not viable: requires single argument '__arr', but 2 arguments were provided
[build]     constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
[build]               ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/span:400:41: note: candidate constructor not viable: requires 0 arguments, but 2 were provided
[build]     _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {}
[build]                                         ^
[build] 1 error generated.

问题原因

从报错信息可以确认,macOS 12.3 SDK配套的旧版本libc++存在实现缺陷:

  • 该版本的std::span仅支持接收原生指针(pointer类型)的(指针,长度)、(起始指针,结束指针)构造重载,没有实现C++20标准规定的迭代器对构造函数
  • 旧版libc++中std::vector的迭代器是封装类型std::__wrap_iter,无法隐式转换为原生指针,因此传入迭代器时匹配不到可用构造函数,触发编译错误。

修复方案

两种兼容旧版libc++的写法,任选其一即可:

  • 手动取出vector的原生数据指针,用指针+长度的方式构造span,兼容性最好:
    const auto* base_ptr = level.floor_datas.data() + offset;
    const auto count = get_floor_data_count(header);
    auto span = std::span<const unsigned short>(base_ptr, count);
    
  • 对迭代器调用base()方法取出内部持有的原生指针(libc的__wrap_iter、GCC libstdc的vector迭代器均支持该方法):
    auto start = level.floor_datas.begin() + offset;
    auto end = start + get_floor_data_count(header);
    auto span = std::span<const unsigned short>(start.base(), end.base());
    

升级Xcode到14及以上版本、使用更新的macOS SDK后,新版libc++已经补全了迭代器对构造的支持,原写法可直接编译通过。


内容的提问来源于stack exchange,提问作者user3001150

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 04:15:28