Search code examples
c++c++20std-span

What is the difference between the two overloads of std::span::subspan()


It appears that std::span<T,Extent>::subspan has two overloads.

Here (live):

#include <array>
#include <span>
#include <fmt/core.h>


void show_sizes( const std::span<const char* const> command_line_arguments )
{
    fmt::print( "{}\n", command_line_arguments.size( ) );

    const auto command_line_options { command_line_arguments.subspan( 1 ) }; // this
    const auto command_line_options { command_line_arguments.subspan<1>( ) }; // or this?

    fmt::print( "{}\n", command_line_options.size( ) );
}

int main( int argc, char* argv[] )
{
    const std::span<const char* const> command_line_arguments { argv, static_cast<std::size_t>( argc ) };
    show_sizes( command_line_arguments );
}

Which one is better for the above case (since we already know that argc can't be less than 1 so there's probably no chance for UB)?

What is really the purpose of the overload that takes no arguments? Is it there for better compile-time evaluation? What is the advantage?


Solution

  • The first overload is for fixed-size spans if their extent can be known statically. For example:

    // A `std::span<T, 3>` of the last 3 elements
    std::span<T, 5>{...}.subspan<2>();
    
    // A `std::span<T, 5>` of the first 5 elements after skipping the first
    std::span<T>{...}.subspan<1, 5>();
    

    For std::span<T>{...}.subspan<N>() vs std::span<T>{}.subspan(N), there is no difference in behaviour since the size is still not known.