microsoft / microsoft/STL

`<span>`: How cromulent is `span<int, static_cast<size_t>(-2)>`?

Open
#5,280 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

LWG issue needed
Dominant language
C++
Stars
11.1k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

Raised by @frederick-vs-ja in https://github.com/microsoft/STL/pull/5274#discussion_r1951827253.

span<int, static_cast<size_t>(-2)> is bogus, but how bogus? It clearly violates the size_bytes() precondition if called. It also violates all constructor preconditions. But can we static_assert when this type is instantiated? An LWG issue would be nice.

There's implementation divergence: https://godbolt.org/z/7ha8rK18K

#ifdef _MSC_VER
#include <crtdbg.h>
#endif

#include <cstddef>
#include <iostream>
#include <span>
using namespace std;

int main() {
#ifdef _MSC_VER
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
#endif

    constexpr size_t BogusSize = static_cast<size_t>(-2);

    int arr[3]{};
    span<int, BogusSize> sp(arr, BogusSize);  // lies
    cout << "Constructed span." << endl;
    cout << "sp.size_bytes(): " << sp.size_bytes() << endl;
}
  • With VS 2022 17.10 (long before #5274) debug mode, size_bytes() emits a debug assertion:
    Program stdout
    Constructed span.
    Z:/compilers/msvc/14.40.33807-14.40.33811.0/include\span(435) : Assertion failed: size of span in bytes exceeds std::numeric_limits<size_t>::max()
    
  • In #5274, I am static_asserting (unconditionally, regardless of debug mode) when any constructor is instantiated, but not the whole type.
  • With GCC 14.2 libstdc++ debug mode, the constructor emits a debug assertion:
    Program stderr
    /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:165:
    In function:
        constexpr std::span<_Type, _Extent>::span(_It, size_type) [with _It = 
        int*; _Type = int; long unsigned int _Extent = 18446744073709551614; 
        size_type = long unsigned int]
    
    Error: function requires a valid iterator range [first, first + count).
    [...]
    
  • With Clang 19.1.0 libc++, a compiler error is emitted due to the constructor taking an array:
    Compiler stderr
    In file included from <source>:7:
    /opt/compiler-explorer/clang-19.1.0/bin/../include/c++/v1/span:281:79: error: array is too large (18446744073709551614 elements)
      281 |   _LIBCPP_HIDE_FROM_ABI constexpr span(type_identity_t<element_type> (&__arr)[_Extent]) noexcept : __data_{__arr} {}
          |                                                                               ^~~~~~~
    <source>:19:26: note: in instantiation of template class 'std::span<int, 18446744073709551614>' requested here
       19 |     span<int, BogusSize> sp(arr, BogusSize);  // lies
          |                          ^
    

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the std::span constructors and size_bytes() behavior described in the issue, then review PR #5274 and its discussion. Reproduce the sample across MSVC, libstdc++, and libc++ using the linked Compiler Explorer case. Done means the intended handling of the invalid extent is decided and the implementation behavior is made consistent.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.