Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2018-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_SPAN_H6#define BITCOIN_SPAN_H8#include <cassert>9#include <cstddef>10#include <span>11#include <type_traits>12#include <utility>14/** A span is an object that can refer to a contiguous sequence of objects.15*16* Things to be aware of when writing code that deals with spans:17*18* - Similar to references themselves, spans are subject to reference lifetime19* issues. The user is responsible for making sure the objects pointed to by20* a span live as long as the span is used. For example:21*22* std::vector<int> vec{1,2,3,4};23* std::span<int> sp(vec);24* vec.push_back(5);25* printf("%i\n", sp.front()); // UB!26*27* may exhibit undefined behavior, as increasing the size of a vector may28* invalidate references.29*30* - One particular pitfall is that spans can be constructed from temporaries,31* but this is unsafe when the span is stored in a variable, outliving the32* temporary. For example, this will compile, but exhibits undefined behavior:33*34* std::span<const int> sp(std::vector<int>{1, 2, 3});35* printf("%i\n", sp.front()); // UB!36*37* The lifetime of the vector ends when the statement it is created in ends.38* Thus the span is left with a dangling reference, and using it is undefined.39*40* - Due to spans automatic creation from range-like objects (arrays, and data41* types that expose a data() and size() member function), functions that42* accept a span as input parameter can be called with any compatible43* range-like object. For example, this works:44*45* void Foo(std::span<const int> arg);46*47* Foo(std::vector<int>{1, 2, 3}); // Works48*49* This is very useful in cases where a function truly does not care about the50* container, and only about having exactly a range of elements. However it51* may also be surprising to see automatic conversions in this case.52*53* When a function accepts a span with a mutable element type, it will not54* accept temporaries; only variables or other references. For example:55*56* void FooMut(std::span<int> arg);57*58* FooMut(std::vector<int>{1, 2, 3}); // Does not compile59* std::vector<int> baz{1, 2, 3};60* FooMut(baz); // Works61*62* This is similar to how functions that take (non-const) lvalue references63* as input cannot accept temporaries. This does not work either:64*65* void FooVec(std::vector<int>& arg);66* FooVec(std::vector<int>{1, 2, 3}); // Does not compile67*68* The idea is that if a function accepts a mutable reference, a meaningful69* result will be present in that variable after the call. Passing a temporary70* is useless in that context.71*/73/** Pop the last element off a span, and return a reference to that element. */74template <typename T>75T& SpanPopBack(std::span<T>& span)76{77size_t size = span.size();78T& back = span.back();79span = span.first(size - 1);80return back;81}83template <typename V>84auto MakeByteSpan(const V& v) noexcept85{86return std::as_bytes(std::span{v});87}88template <typename V>89auto MakeWritableByteSpan(V&& v) noexcept90{91return std::as_writable_bytes(std::span{std::forward<V>(v)});92}94// Helper functions to safely cast basic byte pointers to unsigned char pointers.95inline unsigned char* UCharCast(char* c) { return reinterpret_cast<unsigned char*>(c); }96inline unsigned char* UCharCast(unsigned char* c) { return c; }97inline unsigned char* UCharCast(signed char* c) { return reinterpret_cast<unsigned char*>(c); }98inline unsigned char* UCharCast(std::byte* c) { return reinterpret_cast<unsigned char*>(c); }99inline const unsigned char* UCharCast(const char* c) { return reinterpret_cast<const unsigned char*>(c); }100inline const unsigned char* UCharCast(const unsigned char* c) { return c; }101inline const unsigned char* UCharCast(const signed char* c) { return reinterpret_cast<const unsigned char*>(c); }102inline const unsigned char* UCharCast(const std::byte* c) { return reinterpret_cast<const unsigned char*>(c); }103// Helper concept for the basic byte types.104template <typename B>105concept BasicByte = requires { UCharCast(std::span<B>{}.data()); };107// Helper function to safely convert a span to a span<[const] unsigned char>.108template <typename T, size_t N> constexpr auto UCharSpanCast(std::span<T, N> s) { return std::span<std::remove_pointer_t<decltype(UCharCast(s.data()))>, N>{UCharCast(s.data()), s.size()}; }110/** Like the std::span constructor, but for (const) unsigned char member types only. Only works for (un)signed char containers. */111template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }112template <typename V> constexpr auto MakeWritableUCharSpan(V&& v) -> decltype(UCharSpanCast(std::span{std::forward<V>(v)})) { return UCharSpanCast(std::span{std::forward<V>(v)}); }114#endif // BITCOIN_SPAN_H
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.