std::end,std::cend(3)

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

✨ std::end,std::cend(3) β€” from the C++ Standard Libary manual ✨

okay bestie, gather round πŸ’– this is the whole std::end / std::cend situation from the C++ Standard Libary manual, section (3). Yes, the manual spells it β€œLibary” β€” we are not fixing it, we are respecting the iconique typo, periodt.

πŸŽ€ NAME πŸŽ€

std::end, std::cend β€” literally the functions themselves, bestie. The original NAME line is basically std::end,std::cend - std::end,std::cend, which is the most self-referential slay ever. It’s giving β€œI return the end iterator” energy.

🌈 Synopsis 🌈

First up, these bad boys live in a whole pile of headers. The way std::end is everywhere is highkey main character energy:

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

And here’s the synopsis, with all the exact signatures and version tags:

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

template< class C >                                   (since C++11)
auto end( const C& c ) -> decltype(c.end());          (2) (constexpr since C++17)

template< class T, std::size_t N >                    (3) (since C++11)
T* end( T (&array)[N] );                              (until C++14)

template< class T, std::size_t N >                    (since C++14)
constexpr T* end( T (&array)[N] ) noexcept;

template< class C >                                   (4) (since C++14)
constexpr auto cend( const C& c ) noexcept(/* see below */)
    -> decltype(std::end(c));

It returns an iterator to the end β€” and bestie, that means the element after the last element, not the last element itself. That’s the whole bit, no cap.

  • 1,2) Returns c.end(), which is typically an iterator one past the end of the sequence represented by c.
  • 1) If C is a standard Container, returns a C::iterator object.
  • 2) If C is a standard Container, returns a C::const_iterator object.
  • 3) Returns a pointer to the end of array.
  • 4) Returns std::end(c), with c always treated as const-qualified. If C is a standard Container, returns a C::const_iterator object.

Also the original has a diagram placeholder called range-begin-end.svg β€” imagine a lil range with begin and end, very demure, very mindful πŸŽ€.

🌸 Parameters 🌸

  • c β€” a container or view with an end member function.
  • array β€” an array of arbitrary type.

πŸ’– Return value πŸ’–

  • 1,2) c.end()
  • 3) array + N
  • 4) c.end()

πŸ’… Exceptions πŸ’…

For overload 4), the noexcept specification is literally:

noexcept(noexcept(std::end(c)))

πŸ¦‹ Overloads πŸ¦‹

Custom overloads of end may be provided for classes and enumerations that do not expose a suitable end() member function, yet can be iterated. The following overloads are already provided by the standard library:

  • std::end(std::initializer_list) β€” specializes std::end; (C++11), function template.
  • std::end(std::valarray) β€” specializes std::end; (C++11), function template.
  • begin(std::filesystem::directory_iterator), end(std::filesystem::directory_iterator) β€” range-based for loop support; (C++17), function.
  • begin(std::filesystem::recursive_directory_iterator), end(std::filesystem::recursive_directory_iterator) β€” range-based for loop support; (C++17), function.

Similar to the use of swap (described in Swappable), typical use of the end function in generic context is an equivalent of using std::end; end(arg);, which lets both the ADL-selected overloads for user-defined types and the standard library function templates appear in the same overload set.

template<typename Container, typename Function>
void for_each(Container&& cont, Function f)
{
    using std::begin;
    auto it = begin(cont);
    using std::end;
    auto end_it = end(cont);

    for (; it != end_it; ++it)
        f(*it);
}

Overloads of end found by argument-dependent lookup can be used to customize the behavior of std::ranges::end, std::ranges::cend, and (since C++20) other customization pointer objects depending on std::ranges::end.

🌟 Notes 🌟

  • The non-array overloads exactly reflect the behavior of C::end(). Their effects may be surprising if the member function does not have a reasonable implementation.
  • std::cend is introduced for unification of member and non-member range accesses. See also LWG issue 2128.
  • If C is a shallow-const view, std::cend may return a mutable iterator. Such behavior is unexpected for some users. See also P2276 and P2278.

πŸ“ Example πŸ“

The original says // Run this code, so go off:

#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v = {3, 1, 4};
    if (std::find(std::begin(v), std::end(v), 5) != std::end(v))
        std::cout << "Found a 5 in vector v!\n";

    int w[] = {5, 10, 15};
    if (std::find(std::begin(w), std::end(w), 5) != std::end(w))
        std::cout << "Found a 5 in array w!\n";
}

πŸ’» Output πŸ’»

Found a 5 in array w!

πŸ”₯ See also πŸ”₯

  • begin, cbegin β€” returns an iterator to the beginning of a container or array; version tags in the original: (C++11), (C++14); both are function templates.
  • ranges::end β€” returns a sentinel indicating the end of a range; (C++20), customization point object.
  • ranges::cend β€” returns a sentinel indicating the end of a read-only range; (C++20), customization point object.

πŸ‘‘ Category πŸ‘‘

  • * conditionally noexcept

mwah πŸ’‹ that’s the whole page, bestie. Source/version/date at the bottom: http://cppreference.com, 2024.06.10, std::end,std::cend(3). Go be the main character of your generic range loop 🫢✨

πŸ“¦ where this page comes from