std::ranges::data(3)

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

πŸ’… std::ranges::data πŸ’…

hey bestie 🫢 welcome to the std::ranges::data page from the C++ Standard Libary manual. this one is a customization point object and it's giving β€œpointer to the first element of a contiguous range” main character energy. let's get into it ✨

πŸŽ€ NAME πŸŽ€

std::ranges::data - std::ranges::data

okay yes the name is literally the same twice, no cap 😭 that's how the page says it.


✨ Synopsis ✨

okay so first: it's defined in header <ranges>. it's also defined in header <iterator>.

then the synopsis goes like this:

inline namespace /* unspecified */ {

    inline constexpr /* unspecified */ data = /*        (since C++20)
unspecified */;
(customization point object)

}

(that (customization point object) note? yes bestie, that's what it is πŸ’…)

πŸ“ž Call signature πŸ“ž

the call signature is:

template< class T >

    requires /* see below */                            (since C++20)
constexpr std::remove_reference_t<

    ranges::range_reference_t<T>>* data( T&& t );

and what does it do? it returns a pointer to the first element of a contiguous range. periodt πŸ”₯

now the caveats, because of course there are caveats:

if T is an array type and std::remove_all_extents_t<std::remove_reference_t<T>> is incomplete, then the call to ranges::data is ill-formed, no diagnostic required. (translation: the compiler can just refuse without a cute little error message 😭)

if the argument is an lvalue or ranges::enable_borrowed_range<std::remove_cv_t<T>> is true, a call to ranges::data is expression-equivalent to:

  1. decay-copy(t.data()) (until C++23) or auto(t.data()) (since C++23), if that expression is valid and its type is a pointer to an object type.
  2. otherwise, std::to_address(ranges::begin(t)), if the expression ranges::begin(t) is valid and its type models std::contiguous_iterator.

in all other cases, a call to ranges::data is ill-formed, which can result in substitution failure when ranges::data(e) appears in the immediate context of a template instantiation. so yeah, vibe check can fail at compile time πŸ’€

🧠 Notes 🧠

if the argument is an rvalue (i.e. T is an object type) and ranges::enable_borrowed_range<std::remove_cv_t<T>> is false, the call to ranges::data is ill-formed, which also results in substitution failure.

if ranges::data(e) is valid for an expression e, then it returns a pointer to an object.

the C++20 standard requires that if the underlying data function call returns a prvalue, the return value is move-constructed from the materialized temporary object. all implementations directly return the prvalue instead. the requirement is corrected by the post-C++20 proposal P0849R8 to match the implementations. (so the standard had a little oopsie and P0849R8 fixed the fit πŸ’…)

πŸŽ€ Example πŸŽ€

// Run this code

#include <cstring>
#include <iostream>
#include <ranges>
#include <string>

int main()
{
    std::string s{"Hello world!\n"};

    char a[20]; // storage for a C-style string
    std::strcpy(a, std::ranges::data(s));
    // [data(s), data(s) + size(s)] is guaranteed to be an NTBS

    std::cout << a;
}

πŸ’» Output πŸ’»

Hello world!

πŸ‘€ See also πŸ‘€

  • ranges::cdata β€” obtains a pointer to the beginning of a read-only contiguous range (C++20) (customization point object)
  • ranges::begin β€” returns an iterator to the beginning of a range (C++20) (customization point object)
  • data β€” obtains the pointer to the underlying array (C++17) (function template)

okay that's the whole page, bestie 🫢 sourced from http://cppreference.com, version/date 2024.06.10, and it's the std::ranges::data(3) page. byeee πŸ’–βœ¨

πŸ“¦ where this page comes from