[libcamera-devel] [PATCH 1/3] libcamera: utils: Add a new make_array() function

Laurent Pinchart laurent.pinchart at ideasonboard.com
Mon Jan 20 18:38:14 CET 2020


Add a custom implementation of std::make_array() as defined by the
library fundamentals TS v2 ([1]). The function is useful to initialize
static arrays without requiring manually specifying the number of
elements, which could lead to bugs when the specified size is larger
than the number of initializers.

This is an experimental feature in the C++ standard, and while available
in <experimental/array> in stdlibc++ from g++-6 onwards, it is not
provided by libc++.

[1] https://en.cppreference.com/w/cpp/experimental/make_array

Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 Documentation/Doxyfile.in     |  1 +
 src/libcamera/include/utils.h | 42 +++++++++++++++++++++++++++++++++++
 src/libcamera/utils.cpp       | 14 ++++++++++++
 3 files changed, 57 insertions(+)

diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
index 8e6fbdbb92b6..6de59d407e7b 100644
--- a/Documentation/Doxyfile.in
+++ b/Documentation/Doxyfile.in
@@ -877,6 +877,7 @@ EXCLUDE_SYMBOLS        = libcamera::BoundMethodArgs \
                          libcamera::BoundMethodPackBase \
                          libcamera::BoundMethodStatic \
                          libcamera::SignalBase \
+                         *::details::* \
                          std::*
 
 # The EXAMPLE_PATH tag can be used to specify one or more files or directories
diff --git a/src/libcamera/include/utils.h b/src/libcamera/include/utils.h
index e467eb21c518..6e9b9259456a 100644
--- a/src/libcamera/include/utils.h
+++ b/src/libcamera/include/utils.h
@@ -8,12 +8,15 @@
 #define __LIBCAMERA_UTILS_H__
 
 #include <algorithm>
+#include <array>
 #include <chrono>
+#include <functional>
 #include <memory>
 #include <ostream>
 #include <string>
 #include <string.h>
 #include <sys/time.h>
+#include <type_traits>
 
 #define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
 
@@ -108,6 +111,45 @@ inline _hex hex<uint64_t>(uint64_t value, unsigned int width)
 
 size_t strlcpy(char *dst, const char *src, size_t size);
 
+namespace details {
+
+namespace make_array {
+
+	template<class B>
+	struct negation : std::integral_constant<bool, !bool(B::value)> {};
+
+	template<class...> struct conjunction : std::true_type {};
+	template<class B1> struct conjunction<B1> : B1 {};
+	template<class B1, class... Bn>
+	struct conjunction<B1, Bn...>
+		: std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
+
+	template<class> struct is_ref_wrapper : std::false_type {};
+	template<class T> struct is_ref_wrapper<std::reference_wrapper<T>> : std::true_type {};
+
+	template<class D, class...>
+	struct return_type_helper {
+		using type = D;
+	};
+	template <class... Types>
+	struct return_type_helper<void, Types...> : std::common_type<Types...> {
+		static_assert(conjunction<negation<is_ref_wrapper<std::decay_t<Types>>>...>::value,
+			      "Types cannot contain reference_wrappers when D is void");
+	};
+
+	template<class D, class... Types>
+	using return_type = std::array<typename return_type_helper<D, Types...>::type,
+				       sizeof...(Types)>;
+} /* namespace make_array */
+
+} /* namespace details */
+
+template<class D = void, class... Types>
+constexpr details::make_array::return_type<D, Types...> make_array(Types&&... t)
+{
+	return {std::forward<Types>(t)... };
+}
+
 } /* namespace utils */
 
 } /* namespace libcamera */
diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp
index 4beffdab5eb6..b639cfa83d0c 100644
--- a/src/libcamera/utils.cpp
+++ b/src/libcamera/utils.cpp
@@ -199,6 +199,20 @@ size_t strlcpy(char *dst, const char *src, size_t size)
 	return strlen(src);
 }
 
+/**
+ * \fn template<class D, class... Types> libcamera::utils::make_array(Types&&... t)
+ * \brief Create a std::array with automatic deduction of element type and count
+ * \param[in] t The initialization values for the array elements
+ *
+ * This function creates and returns an instance of std::array whose size is
+ * equal to the number of arguments. If the template argument \a D is void, the
+ * array element type is deduced from the elements through
+ * std::common_types_t<Types...>. Otherwise it is set to D. The elements are
+ * initialized from the corresponding arguments.
+ *
+ * \return A std::array initialized from the arguments
+ */
+
 } /* namespace utils */
 
 } /* namespace libcamera */
-- 
Regards,

Laurent Pinchart



More information about the libcamera-devel mailing list