From patchwork Mon Aug 31 13:23:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 28154 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id D86D7C3346 for ; Mon, 31 Aug 2026 13:23:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 11310684C2; Mon, 31 Aug 2026 15:23:23 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="OvDKsUTD"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7FEF5684BA for ; Mon, 31 Aug 2026 15:23:16 +0200 (CEST) Received: from pb-laptop.local (185.221.143.32.nat.pool.zt.hu [185.221.143.32]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E2B871E7 for ; Mon, 31 Aug 2026 15:21:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1788182507; bh=eclQWhg9VfM7+cDkYZ1Ufxlm1M+SfCd/Eo0fDu/njxU=; h=From:To:Subject:Date:In-Reply-To:References:From; b=OvDKsUTD7KDeXZujyMVZ5jZpp/BRuE16yXr9HXBn0czauaagx/mVv0LJJjUCsDWKj NN4gdYYBgHR6Azqca4zNEbqQT2Rl9kgRyw+Qr29u7QCZGtXXPAed69CKv6Niqw1QLc dUA3wDwk84dgYZZmpXSJ9K8MN/Pg6GlIjKmxapts= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 3/3] libcamera: base: span: Remove Date: Mon, 31 Aug 2026 15:23:12 +0200 Message-ID: <20260831132312.619946-4-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260831132312.619946-1-barnabas.pocze@ideasonboard.com> References: <20260831132312.619946-1-barnabas.pocze@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" With the switch to C++20, this type has largely become unnecessary, so remove it, but leave a deprecated alias instructing users to use `std::span`. Signed-off-by: Barnabás Pőcze Reviewed-by: Kieran Bingham --- include/libcamera/base/span.h | 405 +--------------------------------- test/meson.build | 1 - test/span.cpp | 205 ----------------- 3 files changed, 5 insertions(+), 606 deletions(-) delete mode 100644 test/span.cpp diff --git a/include/libcamera/base/span.h b/include/libcamera/base/span.h index 5c7a98d8e7..ca10aa2954 100644 --- a/include/libcamera/base/span.h +++ b/include/libcamera/base/span.h @@ -7,408 +7,13 @@ #pragma once -#include -#include -#include -#include +#include -namespace libcamera { - -static constexpr std::size_t dynamic_extent = std::numeric_limits::max(); - -template -class Span; - -namespace details { - -template -struct is_array : public std::false_type { -}; - -template -struct is_array> : public std::true_type { -}; - -template -struct is_libcamera_span : public std::false_type { -}; - -template -struct is_libcamera_span> : public std::true_type { -}; - -} /* namespace details */ - -namespace utils { - -template -constexpr auto size(const C &c) -> decltype(c.size()) -{ - return c.size(); -} - -template -constexpr auto data(const C &c) -> decltype(c.data()) -{ - return c.data(); -} - -template -constexpr auto data(C &c) -> decltype(c.data()) -{ - return c.data(); -} - -template -constexpr T *data(T (&array)[N]) noexcept -{ - return array; -} - -template -struct tuple_element; - -template -struct tuple_element> { - using type = T; -}; - -template -struct tuple_size; - -template -struct tuple_size> : public std::integral_constant { -}; - -template -struct tuple_size>; - -} /* namespace utils */ - -template -class Span -{ -public: - using element_type = T; - using value_type = typename std::remove_cv_t; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - using pointer = T *; - using const_pointer = const T *; - using reference = T &; - using const_reference = const T &; - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - static constexpr std::size_t extent = Extent; - - template> - constexpr Span() noexcept - : data_(nullptr) - { - } - - explicit constexpr Span(pointer ptr, [[maybe_unused]] size_type count) - : data_(ptr) - { - } - - explicit constexpr Span(pointer first, [[maybe_unused]] pointer last) - : data_(first) - { - } - - template - constexpr Span(element_type (&arr)[N], - std::enable_if_t (*)[], - element_type (*)[]>::value && - N == Extent, - std::nullptr_t> = nullptr) noexcept - : data_(arr) - { - } - - template - constexpr Span(std::array &arr, - std::enable_if_t (*)[], - element_type (*)[]>::value && - N == Extent, - std::nullptr_t> = nullptr) noexcept - : data_(arr.data()) - { - } - - template - constexpr Span(const std::array &arr, - std::enable_if_t (*)[], - element_type (*)[]>::value && - N == Extent, - std::nullptr_t> = nullptr) noexcept - : data_(arr.data()) - { - } - - template - explicit constexpr Span(Container &cont, - std::enable_if_t::value && - !details::is_array::value && - !std::is_array::value && - std::is_convertible (*)[], - element_type (*)[]>::value, - std::nullptr_t> = nullptr) - : data_(utils::data(cont)) - { - } - - template - explicit constexpr Span(const Container &cont, - std::enable_if_t::value && - !details::is_array::value && - !std::is_array::value && - std::is_convertible (*)[], - element_type (*)[]>::value, - std::nullptr_t> = nullptr) - : data_(utils::data(cont)) - { - static_assert(utils::size(cont) == Extent, "Size mismatch"); - } - - template - explicit constexpr Span(const Span &s, - std::enable_if_t::value && - N == Extent, - std::nullptr_t> = nullptr) noexcept - : data_(s.data()) - { - } - - constexpr Span(const Span &other) noexcept = default; - constexpr Span &operator=(const Span &other) noexcept = default; +/* \todo Remove this header. */ - constexpr iterator begin() const { return data(); } - constexpr const_iterator cbegin() const { return begin(); } - constexpr iterator end() const { return data() + size(); } - constexpr const_iterator cend() const { return end(); } - constexpr reverse_iterator rbegin() const { return reverse_iterator(end()); } - constexpr const_reverse_iterator crbegin() const { return rbegin(); } - constexpr reverse_iterator rend() const { return reverse_iterator(begin()); } - constexpr const_reverse_iterator crend() const { return rend(); } - - constexpr reference front() const { return *data(); } - constexpr reference back() const { return *(data() + size() - 1); } - constexpr reference operator[](size_type idx) const { return data()[idx]; } - constexpr pointer data() const noexcept { return data_; } - - constexpr size_type size() const noexcept { return Extent; } - constexpr size_type size_bytes() const noexcept { return size() * sizeof(element_type); } - constexpr bool empty() const noexcept { return size() == 0; } - - template - constexpr Span first() const - { - static_assert(Count <= Extent, "Count larger than size"); - return Span{ data(), Count }; - } - - constexpr Span first(std::size_t Count) const - { - return Span{ data(), Count }; - } - - template - constexpr Span last() const - { - static_assert(Count <= Extent, "Count larger than size"); - return Span{ data() + size() - Count, Count }; - } - - constexpr Span last(std::size_t Count) const - { - return Span{ data() + size() - Count, Count }; - } - - template - constexpr Span subspan() const - { - static_assert(Offset <= Extent, "Offset larger than size"); - static_assert(Count == dynamic_extent || Count + Offset <= Extent, - "Offset + Count larger than size"); - return Span{ - data() + Offset, - Count == dynamic_extent ? size() - Offset : Count - }; - } - - constexpr Span - subspan(std::size_t Offset, std::size_t Count = dynamic_extent) const - { - return Span{ - data() + Offset, - Count == dynamic_extent ? size() - Offset : Count - }; - } - -private: - pointer data_; -}; - -template -class Span -{ -public: - using element_type = T; - using value_type = typename std::remove_cv_t; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - using pointer = T *; - using const_pointer = const T *; - using reference = T &; - using const_reference = const T &; - using iterator = T *; - using const_iterator = const T *; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - static constexpr std::size_t extent = dynamic_extent; - - constexpr Span() noexcept - : data_(nullptr), size_(0) - { - } - - constexpr Span(pointer ptr, size_type count) - : data_(ptr), size_(count) - { - } - - constexpr Span(pointer first, pointer last) - : data_(first), size_(last - first) - { - } - - template - constexpr Span(element_type (&arr)[N], - std::enable_if_t (*)[], - element_type (*)[]>::value, - std::nullptr_t> = nullptr) noexcept - : data_(arr), size_(N) - { - } - - template - constexpr Span(std::array &arr, - std::enable_if_t (*)[], - element_type (*)[]>::value, - std::nullptr_t> = nullptr) noexcept - : data_(utils::data(arr)), size_(N) - { - } - - template - constexpr Span(const std::array &arr) noexcept - : data_(utils::data(arr)), size_(N) - { - } - - template - constexpr Span(Container &cont, - std::enable_if_t::value && - !details::is_array::value && - !std::is_array::value && - std::is_convertible (*)[], - element_type (*)[]>::value, - std::nullptr_t> = nullptr) - : data_(utils::data(cont)), size_(utils::size(cont)) - { - } - - template - constexpr Span(const Container &cont, - std::enable_if_t::value && - !details::is_array::value && - !std::is_array::value && - std::is_convertible (*)[], - element_type (*)[]>::value, - std::nullptr_t> = nullptr) - : data_(utils::data(cont)), size_(utils::size(cont)) - { - } - - template - constexpr Span(const Span &s, - std::enable_if_t::value, - std::nullptr_t> = nullptr) noexcept - : data_(s.data()), size_(s.size()) - { - } - - constexpr Span(const Span &other) noexcept = default; - constexpr Span &operator=(const Span &other) noexcept = default; - - constexpr iterator begin() const { return data(); } - constexpr const_iterator cbegin() const { return begin(); } - constexpr iterator end() const { return data() + size(); } - constexpr const_iterator cend() const { return end(); } - constexpr reverse_iterator rbegin() const { return reverse_iterator(end()); } - constexpr const_reverse_iterator crbegin() const { return rbegin(); } - constexpr reverse_iterator rend() const { return reverse_iterator(begin()); } - constexpr const_reverse_iterator crend() const { return rend(); } - - constexpr reference front() const { return *data(); } - constexpr reference back() const { return *(data() + size() - 1); } - constexpr reference operator[](size_type idx) const { return data()[idx]; } - constexpr pointer data() const noexcept { return data_; } - - constexpr size_type size() const noexcept { return size_; } - constexpr size_type size_bytes() const noexcept { return size() * sizeof(element_type); } - constexpr bool empty() const noexcept { return size() == 0; } - - template - constexpr Span first() const - { - return Span{ data(), Count }; - } - - constexpr Span first(std::size_t Count) const - { - return { data(), Count }; - } - - template - constexpr Span last() const - { - return Span{ data() + size() - Count, Count }; - } - - constexpr Span last(std::size_t Count) const - { - return Span{ data() + size() - Count, Count }; - } - - template - constexpr Span subspan() const - { - return Span{ - data() + Offset, - Count == dynamic_extent ? size() - Offset : Count - }; - } - - constexpr Span - subspan(std::size_t Offset, std::size_t Count = dynamic_extent) const - { - return Span{ - data() + Offset, - Count == dynamic_extent ? size() - Offset : Count - }; - } +namespace libcamera { -private: - pointer data_; - size_type size_; -}; +template +using Span [[deprecated("use std::span instead")]] = std::span; } /* namespace libcamera */ diff --git a/test/meson.build b/test/meson.build index e4450625ee..363a2829d8 100644 --- a/test/meson.build +++ b/test/meson.build @@ -45,7 +45,6 @@ public_tests = [ {'name': 'geometry', 'sources': ['geometry.cpp']}, {'name': 'public-api', 'sources': ['public-api.cpp']}, {'name': 'signal', 'sources': ['signal.cpp']}, - {'name': 'span', 'sources': ['span.cpp']}, {'name': 'transform', 'sources': ['transform.cpp']}, ] diff --git a/test/span.cpp b/test/span.cpp deleted file mode 100644 index 4b9f3279ad..0000000000 --- a/test/span.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2020, Google Inc. - * - * Span tests - */ - -/* - * Include first to ensure the header is self-contained, as there's no span.cpp - * in libcamera. - */ -#include - -#include -#include -#include - -#include "test.h" - -using namespace std; -using namespace libcamera; - -class SpanTest : public Test -{ -protected: - int run() - { - int i[4]{ 1, 2, 3, 4 }; - std::array a{ 1, 2, 3, 4 }; - const std::array ca{ 1, 2, 3, 4 }; - std::vector v{ 1, 2, 3, 4 }; - const std::vector cv{ 1, 2, 3, 4 }; - - /* - * Compile-test construction and usage of spans with static - * extent. Commented-out tests are expected not to compile, or - * to generate undefined behaviour. - */ - - Span{}; - /* Span{}; */ - - Span{ &i[0], 4 }; - Span{ &i[0], &i[3] }; - - Span{ i }; - /* Span{ i }; */ - /* Span{ i }; */ - - Span{ a }; - Span{ a }; - /* Span{ a }; */ - /* Span{ a }; */ - - Span{ ca }; - /* Span{ ca }; */ - /* Span{ ca }; */ - /* Span{ ca }; */ - - Span{ v }; - Span{ v }; - /* Span{ v }; */ - - Span{ v }; - /* Span{ v }; */ - /* Span{ v }; */ - - Span staticSpan{ i }; - Span{ staticSpan }; - Span{ staticSpan }; - /* Span{ staticSpan }; */ - - staticSpan = Span{ v }; - - if (*staticSpan.begin() != 1) { - std::cout << "Span::begin() failed" << std::endl; - return TestFail; - } - if (*staticSpan.cbegin() != 1) { - std::cout << "Span::cbegin() failed" << std::endl; - return TestFail; - } - staticSpan.end(); - staticSpan.cend(); - if (*staticSpan.rbegin() != 4) { - std::cout << "Span::rbegin() failed" << std::endl; - return TestFail; - } - if (*staticSpan.crbegin() != 4) { - std::cout << "Span::crbegin() failed" << std::endl; - return TestFail; - } - staticSpan.rend(); - staticSpan.crend(); - - staticSpan.front(); - staticSpan.back(); - staticSpan[0]; - staticSpan.data(); - - staticSpan.size(); - staticSpan.size_bytes(); - - staticSpan.empty(); - - staticSpan.first<2>(); - staticSpan.first(2); - /* staticSpan.first<6>(); */ - /* staticSpan.first(6); */ - staticSpan.last<2>(); - staticSpan.last(2); - /* staticSpan.last<6>(); */ - /* staticSpan.last(6); */ - staticSpan.subspan<1>(); - staticSpan.subspan<1, 2>(); - staticSpan.subspan(1); - staticSpan.subspan(1, 2); - /* staticSpan.subspan(2, 4); */ - - /* - * Compile-test construction and usage of spans with dynamic - * extent. Commented-out tests are expected not to compile, or - * to generate undefined behaviour. - */ - - Span{}; - - Span{ &i[0], 4 }; - Span{ &i[0], &i[3] }; - - Span{ i }; - /* Span{ i }; */ - - Span{ a }; - Span{ a }; - /* Span{ a }; */ - - Span{ ca }; - /* Span{ca}; */ - /* Span{ca}; */ - - Span{ v }; - Span{ v }; - /* Span{ v }; */ - - Span{ cv }; - /* Span{ cv }; */ - /* Span{ cv }; */ - - Span dynamicSpan{ i }; - Span{ dynamicSpan }; - Span{ dynamicSpan }; - - dynamicSpan = Span{ a }; - - if (*dynamicSpan.begin() != 1) { - std::cout << "Span::begin() failed" << std::endl; - return TestFail; - } - if (*dynamicSpan.cbegin() != 1) { - std::cout << "Span::cbegin() failed" << std::endl; - return TestFail; - } - dynamicSpan.end(); - dynamicSpan.cend(); - if (*dynamicSpan.rbegin() != 4) { - std::cout << "Span::rbegin() failed" << std::endl; - return TestFail; - } - if (*dynamicSpan.crbegin() != 4) { - std::cout << "Span::crbegin() failed" << std::endl; - return TestFail; - } - dynamicSpan.rend(); - dynamicSpan.crend(); - - dynamicSpan.front(); - dynamicSpan.back(); - dynamicSpan[0]; - dynamicSpan.data(); - - dynamicSpan.size(); - dynamicSpan.size_bytes(); - - dynamicSpan.empty(); - - dynamicSpan.first<2>(); - dynamicSpan.first(2); - /* dynamicSpan.first<6>(); */ - /* dynamicSpan.first(6); */ - dynamicSpan.last<2>(); - dynamicSpan.last(2); - /* dynamicSpan.last<6>(); */ - /* dynamicSpan.last(6); */ - dynamicSpan.subspan<1>(); - dynamicSpan.subspan<1, 2>(); - dynamicSpan.subspan(1); - dynamicSpan.subspan(1, 2); - /* dynamicSpan.subspan(2, 4); */ - - return TestPass; - } -}; - -TEST_REGISTER(SpanTest)