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

Niklas Söderlund niklas.soderlund at ragnatech.se
Wed Jan 22 16:02:08 CET 2020


Hi Laurent,

Thanks for your work.

On 2020-01-20 19:38:14 +0200, Laurent Pinchart wrote:
> 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>

Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>

> ---
>  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
> 
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel

-- 
Regards,
Niklas Söderlund


More information about the libcamera-devel mailing list