C++ Dilinde std::span / std::range
- 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).
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
*****************************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).
*****************************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.
*****************************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
*****************************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.
*****************************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
*****************************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
*****************************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.
*****************************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ı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 }; // HATAstd::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ı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).
*****************************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(); // legalAma yeniden bağlama:
std::array a2{ 0, 8, 15 };
cspn = a2; // HATA: cspn constspan<const int> yeniden bağlanabilir:
std::span<const int> sp { a1 };
sp = a2; // OK (elemanlar const kalır)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}); // OKSpan 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); // legalGeç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).
*****************************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
*****************************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
*****************************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
*****************************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
*****************************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
*****************************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?
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}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)).
************************************/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.
************************************/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