top of page

C++ Dilinde std::span / std::range

  • Writer: Yusuf Hançar
    Yusuf Hançar
  • Dec 26, 2025
  • 11 min read

Updated: Dec 27, 2025


std::span: non-owning view (C++20) ve extent (static/dynamic) modeli

C++20 ile eklenen std::span, contiguous (bitişik) bellek blokları için string_view’ın genelleştirilmiş hâlidir: “pointer + length” şeklinde non-owning bir görünüm sağlar.


  • std::span<T, Extent>: bitişik (contiguous) eleman dizisini sahip olmadan (non-owning) gösteren bir view.

  • Tipik temsili:

    • dynamic extent → T* + size (çoğunlukla 2 word)

    • static extent → sadece T* (çoğunlukla 1 word) (Gerçek sizeof platforma bağlıdır; 32/64 bitte değişebilir.)


template <typename T, std::size_t Extent = std::dynamic_extent>
class std::span;

Extent:

  • std::dynamic_extent ise uzunluk runtime’da tutulur. (C++20)

  • Aksi halde uzunluk compile-time sabittir (static extent).


  1. Static extent vs dynamic extent ve sizeof(span)


1.a — Dizi ile (CTAD → static extent)


#include <span>
#include <iostream>

int main()
{
    int arr[]{ 1, 2, 3 };

    std::span sp = arr;  // CTAD: std::span<int, 3>

    std::cout << "sizeof(sp) : " << sizeof(sp) << "\n";
}
*****************************   
AÇIKLAMA :
- arr bir C dizisidir ve boyu compile-time’da bilinir (3).
- CTAD ile span’ın extent’i static olur: span<int, 3>.
- static extent span çoğunlukla sadece pointer taşır.
- Bu yüzden sizeof(span) genellikle “pointer size” kadardır.
  (64-bit: 8, 32-bit: 4)
*****************************   
CEVAP :
64-bit sistemde tipik çıktı: 8
32-bit sistemde tipik çıktı: 4
*****************************

1.b — Iterator + count ile (dynamic extent)

#include <span>
#include <iostream>
#include <vector>

int main()
{
    std::vector ivec{ 1, 2, 3, 4, 5, 7 };

    std::span sp{ ivec.begin(), 3 };   // std::span<int> (dynamic extent)

    std::cout << "sizeof(sp) : " << sizeof(sp) << "\n";
}
*****************************   
AÇIKLAMA :
- iterator + count kurucusu kullanıldığında span genellikle dynamic extent olur: span<int>.
- dynamic extent span hem pointer hem size tutar.
- Bu yüzden sizeof(span) çoğunlukla 2 word kadardır.
*****************************   
CEVAP :
64-bit sistemde tipik çıktı: 16
32-bit sistemde tipik çıktı: 8
*****************************

  1. Lifetime: span non-owning olduğu için dangling riski


#include <array>
#include <span>

std::span<int> make_span()
{
    std::array<int, 4> arr = { 1, 2, 3, 4 }; // stack üzerinde

    return std::span{ arr };                 // span arr.data()'yı tutar
}

int main ()
{
    auto sp = make_span();   // arr yok oldu -> sp dangling

    (void)sp.data();         // pointer artık dangling, erişim UB
}
*****************************   
AÇIKLAMA :
- span verinin sahibi değildir; sadece pointer + length taşır.
- make_span() bitince arr ömrünü tamamlar.
- Dönen span artık geçersiz belleği işaret eder.
- Bu durum tanımsız davranıştır (UB): crash olabilir, çöp değer okuyabilir.
*****************************   
CEVAP :
Tanımsız davranış (UB).
*****************************

  1. std::dynamic_extent nedir?

#include <span>
#include <limits>

inline constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
*****************************   
AÇIKLAMA :
- std::dynamic_extent, “extent runtime’da belirlenecek” anlamına gelen sentinel değerdir.
- Değeri size_t’nin alabileceği en büyük değerdir (MAX).
- span<T, dynamic_extent> demek: “uzunluk runtime’da tutulur.”
*****************************   
CEVAP :
std::dynamic_extent == size_t maksimum değer.
*****************************

  1. Hangi span static, hangi span dynamic? (extent gözlemi)

#include <array>
#include <iostream>
#include <span>
#include <string_view>
#include <vector>

int main()
{
    auto print = [](std::string_view name, std::size_t ex)
    {
        std::cout << name << ", ";

        if (std::dynamic_extent == ex)
            std::cout << "dynamic extent\n";
        else
            std::cout << "static extent = " << ex << "\n";
    };

    int a[]{1, 2, 3, 4, 5};

    std::span span1{a};                     // CTAD -> span<int,5>
    print("span1", span1.extent);

    std::span<int, std::dynamic_extent> span2{a};  // forced dynamic
    print("span2", span2.extent);

    std::array ar{1, 2, 3, 4, 5};
    std::span span3{ar};                    // CTAD -> span<int,5>
    print("span3", span3.extent);

    std::vector v{1, 2, 3, 4, 5};
    std::span span4{v};                     // span<int> (dynamic)
    print("span4", span4.extent);
}
*****************************   
AÇIKLAMA :
- C array / std::array: boyut compile-time bilindiği için CTAD ile static extent oluşur.
- std::vector: boyut runtime olduğu için span genelde dynamic extent olur (span<int>).
- span.extent, static extent ise sabit değeri; dynamic ise std::dynamic_extent’i verir.
*****************************   
CEVAP :
span1, static extent = 5
span2, dynamic extent
span3, static extent = 5
span4, dynamic extent
*****************************

  1. Default ctor: hangi span default-constructible?


6.a — static extent (N>0) default ctor yok → derleme hatası

#include <span>

int main()
{
    std::span<int, 5> sp; 
}
*****************************   
AÇIKLAMA :
- static extent N>0 olan span, default-constructible değildir.
- Çünkü “hangi belleği göstereceği” bilgisi yoktur.
*****************************   
CEVAP :
Derleme hatası.
*****************************

6.b — extent=0 ve dynamic extent default-constructible

#include <span>
#include <iostream>
#include <array>

int main()
{
    std::span<int, 0> sp0;            // OK
    std::cout << sp0.extent << "\n";  // 0
    std::cout << sp0.size()  << "\n"; // 0

    std::span<int> spd;               // OK (dynamic), boş span
    std::cout << spd.extent << "\n";  // dynamic_extent (çok büyük sayı)
    std::cout << spd.size()  << "\n"; // 0

    int arr[]{1,2,3,4,5};
    std::span<int> sp2{ arr };        // dynamic extent
    std::cout << sp2.extent << "\n";  // dynamic_extent
}
*****************************   
AÇIKLAMA :
- span<int,0> default constructible (zaten size 0 sabit).
- span<int> (dynamic) default constructible; boş (nullptr,0) gibi temsil edilir.
- extent bir “static constexpr” üyedir: türün compile-time bilgisidir.
*****************************   
CEVAP :
Çalışır; sp0.size()==0, spd.size()==0, spd.extent==dynamic_extent.
*****************************

  1. CTAD ile static extent olur

#include <span>
#include <iostream>

int main()
{
    int arr[]{1,2,3,4,5};

    std::span<int> sp1{ arr };    // dynamic extent
    std::span sp2{ arr };         // CTAD -> span<int,5> (static)

    std::cout << sp2.extent << "\n";
}
*****************************   
AÇIKLAMA :
- span<int>{arr} yazarsan dinamik extent seçilmiş olur.
- span{arr} CTAD ile static extent (5) çıkar.
*****************************   
CEVAP : 5
*****************************

  1. extent compile-time kontrolü (if constexpr)

#include <span>
#include <iostream>

int main()
{
    using SP = std::span<int>; // dynamic extent span

    if constexpr (SP::extent == std::dynamic_extent)
        std::cout << "dynamic extent\n";
    else
        std::cout << "static extent\n";
}
*****************************   
AÇIKLAMA :
- extent, nesnenin değil türün sabitidir: S::extent.
- if constexpr compile-time karar verir.
*****************************   
CEVAP : dynamic extent
*****************************

  1. static extent ile vector’dan span: kurallar


9.a — Boyut eşleşiyorsa Çalışır


#include <span>
#include <vector>
#include <cassert>

int main()
{
    std::vector<int> vec{ 1,2,3,4,5,6,7 };

    std::span<int, 7> sp1{ vec };   // OK: vec.size() == 7

    assert(sp1.size() == vec.size());
}
*****************************   
AÇIKLAMA :
- span<int,7> için vector’un boyutunun 7 olması gerekir.
- Bu kontrol genelde runtime’da yapılır; koşul sağlanmazsa precondition ihlali olur.
*****************************   
CEVAP : Çalışır.
*****************************

9.b — Boyut uyuşmazlığı UB değil, “precondition violation” (debug’da assert/terminate olabilir)


#include <span>
#include <vector>

int main()
{
    std::vector<int> vec{ 1,2,3,4,5,6,7 };

    std::span<int, 10> sp{ vec };  // Boyut uymuyor
}
*****************************   
AÇIKLAMA :
- span<int,10> oluşturmak için kaynak range’in en az 10 eleman sunması gerekir.
- Bu sağlanmıyorsa bu bir “contract/precondition” ihlalidir.
- Standart buna “UB” demekten ziyade “program hatası” (ill-formed değil, runtime precondition) olarak görülür;
  bazı STL’ler debug modda assert/terminate eder.
*****************************   
CEVAP :
Program hatası (precondition violation). Debug’da assert/terminate olabilir.
*****************************

  1. iterator+count ctor: static extent ile count uyuşmalı


#include <span>
#include <vector>

int main()
{
    std::vector<int> vec{ 1,2,3,4,5,6,7 };

    std::span<int, 5> sp{ vec.begin(), 5 };  // OK
}
*****************************   
AÇIKLAMA :
- iterator + count kurucusunda:
  - count, span’ın static extent’i ile uyumlu olmalı (5).
  - ayrıca iterator’dan itibaren en az 5 eleman olmalı.
*****************************   
CEVAP : legal
*****************************

  • Uyuşmaz örnekler (program hatası / precondition violation):


std::span<int, 3> sp{ vec.begin(), 5 }; // extent=3 ama count=5 -> hatalı
std::span<int, 8> sp{ vec.begin(), 5 }; // extent=8 ama count=5 -> hatalı

  1. Tür uyumu ve const-correctness


11.a — span<const int> elemanları değiştiremez


#include <span>
#include <vector>

int main()
{
    std::vector ivec{ 1,2,3,4,5,6,7,8,9,10 };

    std::span<const int> sp{ ivec };

    // sp.back() = 45; // HATA: const int& döner
}
*****************************   
AÇIKLAMA :
- span<const int> element type const’tur; view edilen elemanlar salt okunur.
*****************************   
CEVAP :
sp oluşturmak legal; eleman değiştirmek derleme hatası.
*****************************

11.b — Eleman türü dönüşümü yapılamaz


std::span<long long> sp{ ivec }; // HATA
std::span<const int> sp{ ivec };
std::span<int> sp1{ sp };       // HATA: const int* -> int*
std::span<const int> sp{ ivec };
std::span<const long> sp1{ sp }; // HATA: element type farklı
  1. decltype(span) eşitliği: vector vs array span türü aynıdır


#include <span>
#include <vector>
#include <array>
#include <type_traits>

int main()
{
    std::vector ivec{ 1,2,3,4,5 };
    std::array  arr { 1,2,3,4,5 };

    std::span<int> vec_span{ ivec }; 
    std::span<int> arr_span{ arr };

    static_assert(std::same_as<decltype(vec_span), decltype(arr_span)>);
}
*****************************   
AÇIKLAMA :
- İkisi de açıkça span<int> yazıldığı için türleri aynıdır (dynamic extent).
- Eğer CTAD ile yazılsaydı (std::span sp{arr}), arr tarafı static extent olabilirdi.
*****************************   
CEVAP :
Derler (assert holds).
*****************************

  1. const span vs span<const T>


#include <span>
#include <array>

int main()
{
    std::array a1{ 1,2,3,4,5,6,7,8,9,10 };

    const std::span<int> cspn { a1 };     // span nesnesi const
    std::span<const int> sp { a1 };       // elemanlar const
}
*****************************   
AÇIKLAMA :
- const std::span<int>: “span nesnesi” yeniden bağlanamaz/atanamaz ama elemanlar int’tir (değiştirilebilir).
- std::span<const int>: span nesnesi atanabilir ama elemanlar const (değiştirilemez).
*****************************   
CEVAP :
İkisi de legal.
*****************************

  • Eleman değişimi:

const std::span<int> cspn { a1 };
cspn[0] = 42;      // legal (eleman int)
++cspn.back();     // legal

  • Ama yeniden bağlama:


std::array a2{ 0, 8, 15 };
cspn = a2;         // HATA: cspn const

  • span<const int> yeniden bağlanabilir:


std::span<const int> sp { a1 };
sp = a2;           // OK (elemanlar const kalır)

  1. std::span yazdırma örnekleri


#include <span>
#include <iostream>

template <typename T, std::size_t Sz>
void print_span(std::span<T, Sz> sp)
{
    std::cout << "size : " << sp.size() << "\n";

    if constexpr (Sz == std::dynamic_extent)
        std::cout << "dynamic extent\n";
    else
        std::cout << "fixed/static extent\n";

    for (const auto& elem : sp)
        std::cout << elem << " ";

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

14.a — array ile CTAD: static extent

int main()
{
    int arr[]{ 1, 2, 3 };
    std::span sp{ arr };   // span<int,3>

    print_span(sp);
}
*****************************   
AÇIKLAMA :
- std::span sp{arr} CTAD ile static extent üretir (3).
- print_span’da Sz sabit 3 olduğu için compile-time “fixed/static” seçilir.
*****************************   
CEVAP :
size : 3
fixed/static extent
1 2 3
*****************************

14.b — vector ile CTAD: dynamic extent

int main()
{
    std::vector vec{ 2, 4, 6, 8 };
    std::span sp{ vec };   // span<int> (dynamic)

    print_span(sp);
}
*****************************   
AÇIKLAMA :
- vector boyutu runtime olduğu için span dynamic extent olur.
*****************************   
CEVAP :
size : 4
dynamic extent
2 4 6 8
*****************************

14.c — “print_span(array)” neden olmaz?


int main()
{
    int arr[]{ 1, 2, 3 };
    // print_span(arr); // HATA
    print_span(std::span{ arr }); // OK
}
*****************************   
AÇIKLAMA :
- print_span parametresi span<T,Sz> bekliyor; T/Sz çıkarımı doğrudan “array”dan yapılmaz.
- Önce span’a dönüştürmek gerekir: std::span{arr}.
*****************************   
CEVAP :
print_span(arr) -> derleme hatası
print_span(std::span{arr}) -> çalışır
*****************************

  • Aynısı vector için de geçerli:


print_span(vec);            // HATA
print_span(std::span{vec}); // OK

  1. Span ve reallocation: vector büyürse span dangling olur


void print_span(std::span<int> sp)
{
    for (auto i : sp) 
        std::cout << i << " ";

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

int main()
{
    std::vector ivec{ 3, 6, 9, 2, 8 };
    std::span sp(ivec);

    print_span(sp);

    for (int i{}; i < 10; ++i)
        ivec.push_back(i);   // reallocation olabilir

    print_span(sp);          // sp artık dangling olabilir
}
*****************************   
AÇIKLAMA :
- span, vector’un iç buffer’ına pointer tutar.
- push_back kapasiteyi aşarsa vector reallocation yapar ve eski buffer geçersiz olur.
- span güncellenmez; bu yüzden ikinci print_span çağrısı tanımsız davranışa gidebilir.
*****************************   
CEVAP :
İkinci yazdırma UB (dangling) riski taşır.
*****************************
  • Doğru yaklaşım: reallocation sonrası span’ı yeniden bağlamak

sp = ivec;
print_span(sp); // legal

  1. Geçici container’dan span oluşturma: en tehlikeli tuzak


std::vector<int> get_vec()
{
    return { 1, 2, 3, 4, 5, 6 };
}

int main()
{
    std::span sp{ get_vec().begin(), 5 }; // HATALI

    for (auto i : sp)
        std::cout << i << " ";
}
*****************************   
AÇIKLAMA :
- get_vec() geçici vector döndürür; ifade sonunda yok olur.
- begin() pointer/iterator’ı o geçici buffer’ı işaret eder.
- span, artık yaşamayan belleğe bakar → dangling → UB.
*****************************   
CEVAP :
Tanımsız davranış (UB) / crash olabilir.
*****************************

  • Benzer şekilde span döndürmek:


auto get_span()
{
    std::vector<int> ivec{ 1, 2, 3, 4, 5, 6 };

    return std::span(ivec); // HATALI: ivec ölünce span dangling
}
*****************************   
AÇIKLAMA :
- local vector ölünce span geçersizleşir.
*****************************   
CEVAP :
Tanımsız davranış (UB).
*****************************

  1. size_bytes, data, front/back örneği

#include <span>
#include <vector>
#include <iostream>

int main()
{
    std::vector v = { 1, 2, 3, 4, 5 };
    std::span sp{ v }; // dynamic extent

    std::cout << "sp.size() : " << sp.size() << "\n";              // 5
    std::cout << "sp.size_bytes() : " << sp.size_bytes() << "\n";  // 5*sizeof(int)
    std::cout << "sp.extent : " << sp.extent << "\n";              // dynamic_extent

    std::cout << sp[0] << "\n";  // 1

    sp[0] *= 10;
    std::cout << v[0] << "\n";        // 10
    std::cout << sp.front() << "\n";  // 10

    ++sp.front();
    std::cout << v[0] << "\n";        // 11

    sp.back() *= 10;
    std::cout << v.back() << "\n";    // 50

    std::cout << std::boolalpha;
    std::cout << "sp.empty() : " << sp.empty() << "\n";  // false

    for (size_t i{}; i < sp.size(); ++i)
        std::cout << *(sp.data() + i) << " ";

    std::cout << "\n";
}
*****************************   
AÇIKLAMA :
- span elemanlara referans semantiğiyle erişir; değişiklikler v’ye yansır.
- size_bytes = size()*sizeof(T).
- extent dynamic ise std::dynamic_extent değeridir.
- empty() sadece size()==0 kontrolü yapar; underlying container boşaltılırsa span otomatik güncellenmez.
*****************************   
CEVAP :
sp.size() : 5
sp.size_bytes() : 20           (int 4 byte ise)
sp.extent : 4294967295...      (platforma göre)
1
10
10
11
50
sp.empty() : false
11 2 3 4 50
*****************************

  1. String literal’dan span + adaptor kullanımı


#include <span>
#include <ranges>
#include <iostream>

int main()
{
    namespace rng = std::ranges;
    namespace vw  = std::views;

    std::span sp{ "smart code" }; // const char[10] -> span<const char, 10>

    static_assert(rng::view<decltype(sp)>);

    for (auto ch : sp | vw::drop(5) | vw::take(5))
        std::cout << ch;

    std::cout << "\n";
}
*****************************   
AÇIKLAMA :
- String literal bir dizidir; CTAD ile span<const char, N> oluşur (N null dahil).
- span view olduğu için drop/take gibi adaptörlerle zincirlenebilir.
- Burada drop(5) sonrası “code\0” tarafına gelir; take(5) ile “code” basılır.
*****************************   
CEVAP :
code
*****************************
  1. subspan

#include <span>
#include <iostream>

template <typename T, std::size_t N>
void print_span(std::span<T, N> sp)
{
    for (auto i : sp) 
        std::cout << i << " ";

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

int main()
{
    int arr[10]{ 0,1,2,3,4,5,6,7,8,9 };
    std::span sp1{ arr };

    print_span(sp1);

    auto sp2 = sp1.subspan(3, 4);

    std::cout << "sp2.size() : " << sp2.size() << "\n";
    print_span(sp2);
}
*****************************   
AÇIKLAMA :
- subspan(offset,count) span’ın alt penceresini üretir.
- sp1.subspan(3,4) => {3,4,5,6}
*****************************   
CEVAP :
0 1 2 3 4 5 6 7 8 9
sp2.size() : 4
3 4 5 6
*****************************

  1. Iteration yolları + reverse


#include <span>
#include <iostream>
#include <ranges>

int main()
{
    int arr[10]{ 0,1,2,3,4,5,6,7,8,9 };
    std::span sp{ arr };

    for (auto i : sp) std::cout << i;
    std::cout << "\n";

    for (auto i : sp | std::views::reverse) std::cout << i;
    std::cout << "\n";

    for (auto it = sp.begin(); it != sp.end(); ++it) std::cout << *it;
    std::cout << "\n";

    for (auto it = sp.rbegin(); it != sp.rend(); ++it) std::cout << *it;
    std::cout << "\n";
}
*****************************   
AÇIKLAMA :
- span hem range hem view: range-for çalışır.
- views::reverse ile pipeline yapılabilir.
- begin/end ve rbegin/rend ile klasik iterator dolaşımı da mümkündür.
*****************************   
CEVAP :
0123456789
9876543210
0123456789
9876543210
*****************************
  1. first / last static vs dynamic overload


#include <span>
#include <iostream>

template <typename T, std::size_t N>
void print_span(std::span<T, N> sp)
{
    for (auto i : sp) 
        std::cout << i << " ";

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

int main()
{
    int arr[10]{ 0,1,2,3,4,5,6,7,8,9 };
    std::span sp1{ arr }; // span<int,10>

    auto sp2 = sp1.first(3);     // runtime count -> dynamic extent span<int>
    auto sp3 = sp1.first<3>();   // compile-time count -> span<int,3>

    print_span(sp2);
    print_span(sp3);
}
*****************************   
AÇIKLAMA :
- first(n): n runtime verildiği için dönüş tipi genelde dynamic extent span olur.
- first<N>(): N compile-time bilindiği için dönüş tipi static extent span<int,N> olur.
*****************************   
CEVAP :
0 1 2
0 1 2
*****************************

  • last<4>() örneği:

int main()
{
    int arr[10]{ 0,1,2,3,4,5,6,7,8,9 };
    std::span sp1{ arr };

    auto sp2 = sp1.first<3>();
    auto sp3 = sp1.last<4>();

    std::cout << "sp2.size() : " << sp2.size() << "\n";
    print_span(sp2);

    std::cout << "sp3.size() : " << sp3.size() << "\n";
    print_span(sp3);
}
*****************************   
AÇIKLAMA :
- first<3>() => ilk 3 eleman
- last<4>()  => son 4 eleman
*****************************   
CEVAP :
sp2.size() : 3
0 1 2
sp3.size() : 4
6 7 8 9
*****************************
  1. views::counted ile span değil, “counted_view” oluşur


#include <vector>
#include <ranges>
#include <type_traits>
#include <iostream>

int main()
{
    namespace vw = std::views;

    std::vector ivec{ 0, 1, 2, 3, 4, 5, 6 };

    auto rg = vw::counted(ivec.begin(), 5);

    static_assert(std::ranges::view<decltype(rg)>);
    // static_assert(std::same_as<decltype(rg), std::span<int>>); // YANLIŞ
}
*****************************   
AÇIKLAMA :
- views::counted(it,n) bir iterator’dan başlayıp n eleman süren bir view üretir.
- Bu view contiguous olmak zorunda değildir; dolayısıyla span ile aynı tür olamaz.
- Ama “range/view” olarak kullanılabilir; çoğu adaptor ile zincirlenebilir.
*****************************   
CEVAP :
static_assert(view<decltype(rg)>) holds.
decltype(rg) != std::span<int>
*****************************
std::span en verimli nerelerde kullanılır?

  1. API tasarımında: “vector/array pointer+size” karmaşasını bitirir

void process(const int* p, std::size_t n);
#include <span>

void process(std::span<const int> data)
{
    // data.size(), data[i], range-for
}
/***********************************
açıklama : 
-> Çağıran taraf std::vector, std::array, C dizisi, new[] ile gelen buffer… hepsini tek imza ile kabul edersin.

-> Kopyalama yok → zero-copy.

-> size ve data tutarlı bir nesnede → daha az hata.
************************************/
std::vector<int> v{ 1, 2, 3 };
int arr[]{ 4, 5, 6 };

process(v);
process(arr);
process(std::span{arr}.subspan(1)); // {5, 6}

  1. Byte buffer / protokol parse işleri (embedded/automotive için çok tipik)


  • Paketin içinden alanları kopyalamadan okumak:

#include <span>
#include <cstdint>
#include <optional>

std::optional<std::uint16_t> read_u16_be(std::span<const std::uint8_t> buf)
{
    if (buf.size() < 2) 
    {
        return std::nullopt;
    }

    return (std::uint16_t(buf[0]) << 8) | buf[1];
}

std::optional<std::uint32_t> read_u32_be(std::span<const std::uint8_t> buf)
{
    if (buf.size() < 4) 
    {
        return std::nullopt;
    }

    return (std::uint32_t(buf[0]) << 24) |
           (std::uint32_t(buf[1]) << 16) |
           (std::uint32_t(buf[2]) << 8)  |
           (std::uint32_t(buf[3]));
}
struct FrameHeader {
    std::uint16_t id;
    std::uint8_t  dlc;
};

std::optional<FrameHeader> parse_header(std::span<const std::uint8_t> frame)
{
    if (frame.size() < 3) 
    {
        return std::nullopt;
    }

    auto id  = read_u16_be(frame.subspan(0,2));

    if (!id)   
    {
        return std::nullopt;
    }

    return FrameHeader{ *id, frame[2] };
}

/***********************************
“offset hesabı + pointer aritmetiği” daha okunur olur (subspan).

Kopya yok → hızlı.

Sınır kontrolünü tek noktaya çekersin (if (size() < N)).
************************************/

  1. hareketli ortalama/filtre uygulama:

#include <span>

float mean(std::span<const float> val)
{
    float sum = 0.f;

    for (float f : val) 
    {
        sum += f;
    }

    return val.empty() ? 0.f : sum / val.size();
}

void moving_average(std::span<const float> in,  std::span<float> out, std::size_t win)
{
    if (win == 0 || in.size() < win || out.size() != in.size() - win + 1)         
    {
        return;
    }

    for (std::size_t i = 0; i + win <= in.size(); ++i)
    {
        out[i] = mean(in.subspan(i, win));
    }
}

/***********************************
“window = subspan(i, win)” çok okunur.

Allocation yok → real-time sistemlerde idealdir.
************************************/

  1. Birden fazla container destekleyen” utility fonksiyonlar


#include <span>
#include <algorithm>

int clamp_to_range(int val, std::span<const int> allowed)
{
    auto [mn, mx] = std::minmax_element(allowed.begin(), allowed.end());

    return std::clamp(val, *mn, *mx);
}

Ne zaman std::span KULLANMAMALISIN?
  • Sahiplik gerekiyorsa (span owner değildir) → std::vector, std::string, std::array.

  • Kaynak veri reallocate olabilecekse ve span uzun süre saklanacaksa → span’ı uzun ömürlü tutulmamalı, ya da reallocation sonrası yeniden bağlanmalıdır.

  • Contiguous olmayan container (std::list, std::forward_list) → span zaten uygun değildir.











 
 
 

Comments


bottom of page