[v3,01/37] libcamera: utils: Add overloaded visitor helpers
diff mbox series

Message ID 20260423230059.3180987-2-laurent.pinchart@ideasonboard.com
State Superseded
Headers show
Series
  • libcamera: Global configuration file improvements
Related show

Commit Message

Laurent Pinchart April 23, 2026, 11 p.m. UTC
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

std::visit() allows quite elegant type-matching implementation of the
visitor pattern.

The 'overloaded' type helpers allow to define a hierarchy of overloaded
operator() implementations which can be used by std::visit().

Currently only the Virtual pipeline handler uses this type-matching
implementation of std::visit(). To prepare to add another user in the
Mali C55 pipeline handler move the 'overloaded' helper type to
libcamera::utils for easier re-use.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Changes since v8 of "[PATCH v8 0/8] libcamera: mali-c55: Add support for memory-to-memory":

- Small improvements to documentation
- Drop documentation of deduction guide
---
 include/libcamera/base/utils.h             |  9 +++++++
 src/libcamera/base/utils.cpp               | 30 ++++++++++++++++++++++
 src/libcamera/pipeline/virtual/virtual.cpp | 10 ++------
 3 files changed, 41 insertions(+), 8 deletions(-)

Comments

Jacopo Mondi April 24, 2026, 8:22 a.m. UTC | #1
Hi Laurent

On Fri, Apr 24, 2026 at 02:00:23AM +0300, Laurent Pinchart wrote:
> From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>
> std::visit() allows quite elegant type-matching implementation of the
> visitor pattern.
>
> The 'overloaded' type helpers allow to define a hierarchy of overloaded
> operator() implementations which can be used by std::visit().
>
> Currently only the Virtual pipeline handler uses this type-matching
> implementation of std::visit(). To prepare to add another user in the
> Mali C55 pipeline handler move the 'overloaded' helper type to
> libcamera::utils for easier re-use.
>
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> Changes since v8 of "[PATCH v8 0/8] libcamera: mali-c55: Add support for memory-to-memory":
>
> - Small improvements to documentation
> - Drop documentation of deduction guide
> ---

Fine with me
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

>  include/libcamera/base/utils.h             |  9 +++++++
>  src/libcamera/base/utils.cpp               | 30 ++++++++++++++++++++++
>  src/libcamera/pipeline/virtual/virtual.cpp | 10 ++------
>  3 files changed, 41 insertions(+), 8 deletions(-)
>
> diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h
> index 7083b7ce9ce9..b33a4c644a87 100644
> --- a/include/libcamera/base/utils.h
> +++ b/include/libcamera/base/utils.h
> @@ -37,6 +37,15 @@ namespace libcamera {
>
>  namespace utils {
>
> +template<class... Ts>
> +struct overloaded : Ts... {
> +	using Ts::operator()...;
> +};
> +#ifndef __DOXYGEN__
> +template<class... Ts>
> +overloaded(Ts...) -> overloaded<Ts...>;
> +#endif
> +
>  const char *basename(const char *path);
>
>  char *secure_getenv(const char *name);
> diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
> index 42a516097be2..4ab2bd863e11 100644
> --- a/src/libcamera/base/utils.cpp
> +++ b/src/libcamera/base/utils.cpp
> @@ -23,6 +23,36 @@ namespace libcamera {
>
>  namespace utils {
>
> +/**
> + * \struct overloaded
> + * \brief Helper type for type-matching std::visit() implementations
> + * \tparam Ts... Template arguments pack of visitors
> + *
> + * Expand the template argument pack \a Ts... to provide overloaded \a
> + * operator() to support type-matching implementations of the visitor design
> + * pattern using std::visit().
> + *
> + * An example is provided by the C++ standard library documentation in the form
> + * of:
> + *
> + * \code{.cpp}
> + * template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
> + * template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
> + *
> + * using var_t = std::variant<int, long, double, std::string>;
> + * std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
> + *
> + * for (auto& v: vec) {
> + * 	std::visit(overloaded {
> + * 		[](auto arg) { std::cout << arg << ' '; },
> + * 		[](double arg) { std::cout << std::fixed << arg << ' '; },
> + * 		[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
> + * 	}, v);
> + * \endcode
> + *
> + * Use this helper to implement type-matching visitors using std::visit().
> + */
> +
>  /**
>   * \brief Strip the directory prefix from the path
>   * \param[in] path The path to process
> diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp
> index efd800ebe3d6..e8ef7e524ccf 100644
> --- a/src/libcamera/pipeline/virtual/virtual.cpp
> +++ b/src/libcamera/pipeline/virtual/virtual.cpp
> @@ -23,6 +23,7 @@
>
>  #include <libcamera/base/flags.h>
>  #include <libcamera/base/log.h>
> +#include <libcamera/base/utils.h>
>
>  #include <libcamera/control_ids.h>
>  #include <libcamera/controls.h>
> @@ -57,13 +58,6 @@ uint64_t currentTimestamp()
>
>  } /* namespace */
>
> -template<class... Ts>
> -struct overloaded : Ts... {
> -	using Ts::operator()...;
> -};
> -template<class... Ts>
> -overloaded(Ts...) -> overloaded<Ts...>;
> -
>  class VirtualCameraConfiguration : public CameraConfiguration
>  {
>  public:
> @@ -428,7 +422,7 @@ bool PipelineHandlerVirtual::initFrameGenerator(Camera *camera)
>  {
>  	auto data = cameraData(camera);
>  	auto &frame = data->config_.frame;
> -	std::visit(overloaded{
> +	std::visit(utils::overloaded{
>  			   [&](TestPattern &testPattern) {
>  				   for (auto &streamConfig : data->streamConfigs_) {
>  					   if (testPattern == TestPattern::DiagonalLines)
> --
> Regards,
>
> Laurent Pinchart
>

Patch
diff mbox series

diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h
index 7083b7ce9ce9..b33a4c644a87 100644
--- a/include/libcamera/base/utils.h
+++ b/include/libcamera/base/utils.h
@@ -37,6 +37,15 @@  namespace libcamera {
 
 namespace utils {
 
+template<class... Ts>
+struct overloaded : Ts... {
+	using Ts::operator()...;
+};
+#ifndef __DOXYGEN__
+template<class... Ts>
+overloaded(Ts...) -> overloaded<Ts...>;
+#endif
+
 const char *basename(const char *path);
 
 char *secure_getenv(const char *name);
diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp
index 42a516097be2..4ab2bd863e11 100644
--- a/src/libcamera/base/utils.cpp
+++ b/src/libcamera/base/utils.cpp
@@ -23,6 +23,36 @@  namespace libcamera {
 
 namespace utils {
 
+/**
+ * \struct overloaded
+ * \brief Helper type for type-matching std::visit() implementations
+ * \tparam Ts... Template arguments pack of visitors
+ *
+ * Expand the template argument pack \a Ts... to provide overloaded \a
+ * operator() to support type-matching implementations of the visitor design
+ * pattern using std::visit().
+ *
+ * An example is provided by the C++ standard library documentation in the form
+ * of:
+ *
+ * \code{.cpp}
+ * template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
+ * template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
+ *
+ * using var_t = std::variant<int, long, double, std::string>;
+ * std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
+ *
+ * for (auto& v: vec) {
+ * 	std::visit(overloaded {
+ * 		[](auto arg) { std::cout << arg << ' '; },
+ * 		[](double arg) { std::cout << std::fixed << arg << ' '; },
+ * 		[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
+ * 	}, v);
+ * \endcode
+ *
+ * Use this helper to implement type-matching visitors using std::visit().
+ */
+
 /**
  * \brief Strip the directory prefix from the path
  * \param[in] path The path to process
diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp
index efd800ebe3d6..e8ef7e524ccf 100644
--- a/src/libcamera/pipeline/virtual/virtual.cpp
+++ b/src/libcamera/pipeline/virtual/virtual.cpp
@@ -23,6 +23,7 @@ 
 
 #include <libcamera/base/flags.h>
 #include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
 
 #include <libcamera/control_ids.h>
 #include <libcamera/controls.h>
@@ -57,13 +58,6 @@  uint64_t currentTimestamp()
 
 } /* namespace */
 
-template<class... Ts>
-struct overloaded : Ts... {
-	using Ts::operator()...;
-};
-template<class... Ts>
-overloaded(Ts...) -> overloaded<Ts...>;
-
 class VirtualCameraConfiguration : public CameraConfiguration
 {
 public:
@@ -428,7 +422,7 @@  bool PipelineHandlerVirtual::initFrameGenerator(Camera *camera)
 {
 	auto data = cameraData(camera);
 	auto &frame = data->config_.frame;
-	std::visit(overloaded{
+	std::visit(utils::overloaded{
 			   [&](TestPattern &testPattern) {
 				   for (auto &streamConfig : data->streamConfigs_) {
 					   if (testPattern == TestPattern::DiagonalLines)