std::size,std::ssize(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸŽ€ NAME πŸŽ€

The NAME line is literally std::size,std::ssize - std::size,std::ssize β€” yes bestie, it's giving "I contain multitudes" energy πŸ’…. This is the std::size,std::ssize(3) page from the C++ Standard Libary manual (that's the spelling up top, we are not correcting it, periodt πŸ’€).


✨ Synopsis ✨

Okay so first things first: this icon lives in a lot of headers. Like, a lot a lot. Defined in header:

  • <array>
  • <deque>
  • <flat_map>
  • <flat_set>
  • <forward_list>
  • <iterator>
  • <list>
  • <map>
  • <regex>
  • <set>
  • <span>
  • <string>
  • <string_view>
  • <unordered_map>
  • <unordered_set>
  • <vector>

Here's the whole synopsis vibe, no cap:

template< class C >
(1) (since C++17)
constexpr auto size( const C& c ) -> decltype(c.size());
template< class C >

constexpr auto ssize( const C& c )
(2) (since C++20)
    -> std::common_type_t<std::ptrdiff_t,

                          std::make_signed_t<decltype(c.size())>>;
template< class T, std::size_t N >
(3) (since C++17)
constexpr std::size_t size( const T (&array)[N] ) noexcept;
template< class T, std::ptrdiff_t N >
(4) (since C++20)
constexpr std::ptrdiff_t ssize( const T (&array)[N] ) noexcept;

Returns the size of the given range. That's the whole job, and honestly? Slay.

1,2) Returns c.size(), converted to the return type if necessary.

3,4) Returns N.


🌸 Parameters 🌸

  • c β€” a container or view with a size member function. It's giving "I have a size() and I'm not afraid to use it" ✨.
  • array β€” an array of arbitrary type. Any type, bestie, we love range.

πŸ’– Return value πŸ’–

  • 1) c.size()
  • 2) static_cast<std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(c.size())>>>(c.size())
  • 3,4) N

⚠️ Exceptions ⚠️

  • 1,2) May throw implementation-defined exceptions. That's the whole warning, so keep it in mind 🫢.

πŸ’« Overloads πŸ’«

Custom overloads of size may be provided for classes and enumerations that do not expose a suitable size() member function, yet can be detected.

Overloads of size found by argument-dependent lookup can be used to customize the behavior of std::ranges::size, std::ranges::ssize, and (since C++20) std::ranges::empty.


πŸ› οΈ Possible implementation πŸ› οΈ

size (1)

template<class C>
constexpr auto size(const C& c) -> decltype(c.size())
{
    return c.size();
}

ssize (2)

template<class C>
constexpr auto ssize(const C& c)
    -> std::common_type_t<std::ptrdiff_t,
                          std::make_signed_t<decltype(c.size())>>
{
    using R = std::common_type_t<std::ptrdiff_t,
                                 std::make_signed_t<decltype(c.size())>>;
    return static_cast<R>(c.size());
}

size (3)

template<class T, std::size_t N>
constexpr std::size_t size(const T (&array)[N]) noexcept
{
    return N;
}

ssize (4)

template<class T, std::ptrdiff_t N>
constexpr std::ptrdiff_t ssize(const T (&array)[N]) noexcept
{
    return N;
}

πŸ“ Notes πŸ“

Feature-test macro tea β˜•:

  • __cpp_lib_nonmember_container_access β€” value 201411L, Std (C++17), feature std::size(), std::data and std::empty
  • __cpp_lib_ssize β€” value 201902L, Std (C++20), feature std::ssize() (2,4) and unsigned std::span::size()

πŸ’» Example πŸ’»

       // Run this code

        #include <cassert>
        #include <cstring>
        #include <iostream>
        #include <vector>

        int main()
        {
            // Works with containers
            std::vector<int> v{3, 1, 4};
            assert(std::size(v) == 3);

            // And works with built-in arrays too
            int a[]{-5, 10, 15};
            // Returns the number of elements (not bytes) as opposed to sizeof
            assert(std::size(a) == 3);
            std::cout << "size of a[]: " << sizeof a << '\n'; // 12, if
       sizeof(int) == 4

            // Provides a safe way (compared to sizeof) of getting string
       buffer size
            const char str[] = "12345";
            // These are fine and give the correct result
            assert(std::size(str) == 6);
            assert(sizeof(str) == 6);

            // But use of sizeof here is a common source of bugs
            const char* str_decayed = "12345";
            // std::cout << std::size(str_decayed) << '\n'; // Usefully fails
       to compile
            std::cout << sizeof(str_decayed) << '\n'; // Prints the size of the
       pointer!

            // Since C++20 the signed size (std::ssize) is available
            auto i = std::ssize(v);
            for (--i; i != -1; --i)
                std::cout << v[i] << (i ? ' ' : '\n');
            assert(i == -1);

            // Note that the string literal includes the ending null character,
       which
            // will be part of the constructed characters array. This makes
       std::size
            // behave differently from std::strlen and std::string::size:
            constexpr char symbols[] = "0123456789";

            static_assert(std::size(symbols) == 11);
            static_assert(std::string(symbols).size() == 10);
            assert(std::strlen(symbols) == 10);
        }

πŸ–¨οΈ Possible output πŸ–¨οΈ

size of a[]: 12
8
4 1 3

πŸ‘€ See also πŸ‘€

  • ptrdiff_t β€” signed integer type returned when subtracting two pointers (typedef)
  • size_t β€” unsigned integer type returned by the sizeof operator (typedef)
  • ranges::size β€” returns an integer equal to the size of a range (C++20) (customization point object)
  • ranges::ssize β€” returns a signed integer equal to the size of a range (C++20) (customization point object)

Source: http://cppreference.com Β· Version/date: 2024.06.10 Β· Page: std::size,std::ssize(3) β€” bye bestie, go get that size, signed or unsigned, and slay πŸ’…βœ¨πŸ¦‹

πŸ“¦ where this page comes from