libcxx与libstdc++的std::span构造器:非模板实现是否符合标准?
Great question! This gets into a key detail of C++ standard library implementations: multiple valid approaches can exist to satisfy the same standard requirements, and both libcxx and libstdc++ are doing things correctly here. Let's break this down step by step:
1. Is libcxx's pointer-based implementation compliant?
Absolutely. Here's why:
- The C++ standard requires these two constructors (cppreference's #2 and #3) to accept inputs where the iterator satisfies
contiguous_iterator, and the reference type is convertible tospan::element_type(with at most cv-qualification changes). - Pointers are explicitly considered
contiguous_iterators by the standard. So libcxx's choice to write non-template overloads for pointers directly aligns with the standard's requirements. - The
_LIBCPP_ASSERTcalls in libcxx enforce the critical constraint: if the span has a fixed extent (notdynamic_extent), the input size must match that extent. This is exactly what the standard mandates.
You might wonder: what about custom contiguous iterators that aren't pointers? Libcxx doesn't miss these cases—either:
- The custom iterator can implicitly convert to a pointer (many do, for compatibility), or
- Libcxx provides additional template overloads (which you might not have seen in the snippet you shared) that handle non-pointer contiguous iterators with the appropriate constraints.
Either way, the implementation stays within the standard's bounds.
2. Is libstdc++'s template+concept implementation redundant?
No, not at all. It's just a different (and equally valid) implementation strategy:
- Libstdc++ follows the standard's template signature almost verbatim, using
contiguous_iteratorand other concepts to explicitly enforce the constraints. This makes the code very readable and directly maps to what cppreference documents. - This approach naturally handles all valid contiguous iterators—pointers, custom iterators, etc.—without needing separate overloads for pointers.
Both implementations trade off slightly:
- Libcxx's pointer overloads avoid template instantiation overhead for the common case of raw pointers.
- Libstdc++'s template approach is more declarative and covers all valid inputs in one place.
Neither is "better"—they're just different ways to meet the same standard requirements.
3. Extending this to array/std::array constructors (#4, #5, #6)
The same logic applies here:
- The standard requires these constructors to accept native arrays or
std::arrayinstances with compatible element types, and enforce size matching for fixed-extent spans. - Libcxx might choose to write non-template or partially specialized overloads for arrays (e.g., taking a reference to a native array of known size) to optimize for common cases.
- Libstdc++ would likely use templates with concepts to explicitly validate the input types and sizes.
Again, both approaches are compliant. The core requirement is that the implementation correctly handles valid inputs, rejects invalid ones (via overload resolution or assertions), and enforces the standard's constraints.
内容的提问来源于stack exchange,提问作者Nelfeal

