std::span::operator=(3)

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

✨ NAME ✨

okay bestie, welcome to std::span::operator=(3) from the C++ Standard Libary manual, section 3. The name is literally std::span::operator= β€” that’s it, that’s the whole name, no cap. πŸ’…

πŸŽ€ Synopsis πŸŽ€

here’s the signature, posted up with main character energy:

constexpr span& operator=( const span& other ) noexcept = default;

(since C++20) β€” yes bestie, this one is living in C++20. ✨

It assigns other to *this. This defaulted assignment operator performs a shallow copy of the data pointer and the size, i.e., after a call to this function, data() == other.data() and size() == other.size(). Translation: it’s matching the pointer and the size, not cloning the whole buffer. 🫢

πŸ’– Parameters πŸ’–

  • other β€” another span to copy from. That’s the whole parameter list, bestie. πŸ™ˆ

🫢 Return value 🫢

*this β€” it returns itself, slay. πŸ’…

🌸 Example 🌸

Run this code, bestie. The commented-out lines are marked // ERROR for a reason; do not uncomment them. 😭

// Run this code

#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <iostream>
#include <span>
#include <string_view>

void print(std::string_view info = "", std::span<const int> span = {},
           std::size_t extent = 0, std::size_t size_of = 0)
{
    if (span.empty())
    {
        std::cout << info << '\n';
        return;
    }

    std::cout << info << '[' << span.size() << "] {";
    std::ranges::for_each(span, [](const int x) { std::cout << ' ' <<
       x; });
    std::cout << " }";

    if (extent)
    {
        std::cout << " extent = ";
        if (extent == std::dynamic_extent)
            std::cout << "dynamic";
        else
            std::cout << extent;
    }

    if (size_of)
        std::cout << ", sizeof = " << size_of;

    std::cout << '\n';
}

int main()
{
    std::array<int,6> a1;
    std::array<int,6> a2;
    a1.fill(3);
    a2.fill(4);

    auto s1 = std::span(a1);
    auto s2 = std::span(a2);
    print("s1", s1, s1.extent, sizeof(s1));
    print("s2", s2, s2.extent, sizeof(s2));

    // Check that assignment performs a shallow copy.
    s1 = s2;
    (s1.data() == s2.data() && s1.size() == s2.size())
        ? print("s1 = s2; is a shallow copy!")
        : print("s1 = s2; is a deep copy!");
    print("s1", s1);

    print("Fill s1 with 5:");
    std::ranges::fill(s1, 5);
    // s2 is also 'updated' since s1 and s2 point to the same data
    assert(std::ranges::equal(s1, s2));
    print("s1", s1);
    print("s2", s2);
    print();

    int a3[]{1, 2, 3, 4};
    int a4[]{2, 3, 4, 5};
    int a5[]{3, 4, 5};

    std::span<int, std::dynamic_extent> dynamic_1{a3};
    std::span<int, std::dynamic_extent> dynamic_2{a4, 3};
    std::span<int, 4> static_1{a3};
    std::span<int, 4> static_2{a4};
    std::span<int, 3> static_3{a5};

    print("dynamic_1", dynamic_1, dynamic_1.extent, sizeof(dynamic_1));
    print("dynamic_2", dynamic_2, dynamic_2.extent, sizeof(dynamic_2));
    print("static_1", static_1, static_1.extent, sizeof(static_1));
    print("static_2", static_2, static_2.extent, sizeof(static_2));
    print("static_3", static_3, static_3.extent, sizeof(static_3));

    dynamic_1 = dynamic_2; // OK
    dynamic_1 = static_1;  // OK
//  static_1 = dynamic_1;  // ERROR: no match for β€˜operator=’
    static_1 = static_2;   // OK: same extents = 4
//  static_1 = static_3;   // ERROR: different extents: 4 and 3
}

πŸ”₯ Output πŸ”₯

s1[6] { 3 3 3 3 3 3 } extent = 6, sizeof = 8
s2[6] { 4 4 4 4 4 4 } extent = 6, sizeof = 8
s1 = s2; is a shallow copy!
s1[6] { 4 4 4 4 4 4 }
Fill s1 with 5:
s1[6] { 5 5 5 5 5 5 }
s2[6] { 5 5 5 5 5 5 }

dynamic_1[4] { 1 2 3 4 } extent = dynamic, sizeof = 16
dynamic_2[3] { 2 3 4 } extent = dynamic, sizeof = 16
static_1[4] { 1 2 3 4 } extent = 4, sizeof = 8
static_2[4] { 2 3 4 5 } extent = 4, sizeof = 8
static_3[3] { 3 4 5 } extent = 3, sizeof = 8

see how s1 = s2; prints s1 = s2; is a shallow copy!? The example is literally proving the shallow-copy vibe β€” and when s1 gets filled with 5, s2 matches because they point to the same data. 🫢

πŸ‘‘ See also πŸ‘‘

  • constructor β€” constructs the span (public member function)
  • data β€” direct access to the underlying contiguous storage (public member function)
  • size β€” returns the number of elements (public member function)

okay, that’s the page! source/version: http://cppreference.com Β· date: 2024.06.10. byeee bestie, go assign those spans πŸ’–βœ¨πŸ«Ά

πŸ“¦ where this page comes from