[v4,2/7] libcamera: utils: Add overloaded visitor helpers
diff mbox series

Message ID 20260313-mali-cru-v4-2-c0d9bc8cd8fa@ideasonboard.com
State New
Headers show
Series
  • libcamera: mali-c55: Add support for memory-to-memory
Related show

Commit Message

Jacopo Mondi March 13, 2026, 11:33 a.m. UTC
std::visit() allows quite elegant type-matching implementation of the
visitor pattern.

The overaloded 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 types to
libcamera::utils for easier re-use.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
---
 include/libcamera/base/utils.h             |  7 ++++++
 src/libcamera/base/utils.cpp               | 35 ++++++++++++++++++++++++++++++
 src/libcamera/pipeline/virtual/virtual.cpp | 10 ++-------
 3 files changed, 44 insertions(+), 8 deletions(-)

Comments

Barnabás Pőcze March 13, 2026, 1:57 p.m. UTC | #1
2026. 03. 13. 12:33 keltezéssel, Jacopo Mondi írta:
> std::visit() allows quite elegant type-matching implementation of the
> visitor pattern.
> 
> The overaloded type helpers allow to define a hierarchy of overloaded
      '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 types to
                                                     type


> libcamera::utils for easier re-use.
> 
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> ---
>   include/libcamera/base/utils.h             |  7 ++++++
>   src/libcamera/base/utils.cpp               | 35 ++++++++++++++++++++++++++++++
>   src/libcamera/pipeline/virtual/virtual.cpp | 10 ++-------
>   3 files changed, 44 insertions(+), 8 deletions(-)
> 
> diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h
> index 7083b7ce9ce9..62c7f89c25a1 100644
> --- a/include/libcamera/base/utils.h
> +++ b/include/libcamera/base/utils.h
> @@ -37,6 +37,13 @@ namespace libcamera {
>   
>   namespace utils {
>   
> +template<class... Ts>
> +struct overloaded : Ts... {
> +	using Ts::operator()...;
> +};
> +template<class... Ts>
> +overloaded(Ts...) -> overloaded<Ts...>;
> +
>   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..a18ca82e8d07 100644
> --- a/src/libcamera/base/utils.cpp
> +++ b/src/libcamera/base/utils.cpp
> @@ -23,6 +23,41 @@ 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
> + * implementations of \a operator().
> + */
> +
> +/**
> + * \var <class... Ts> overloaded(Ts...) -> overloaded<Ts...>

This is just a deduction guide. Does doxygen fail if it is not documented? In any case,
if documented, I think it should just mention that this is a deduction guide necessary
for C++17. And the below text should be moved to the documentation of the type itself.

Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>


> + * \brief Overloaded visitor class for type-matching std::visit implementations
> + * \tparam Ts... Template arguments pack of visitor functions
> + *
> + * std::visit allows quite elegant type-matching implementation of the visitor
> + * pattern. An example is provided by the STL 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)
>
Jacopo Mondi March 13, 2026, 3:04 p.m. UTC | #2
On Fri, Mar 13, 2026 at 02:57:34PM +0100, Barnabás Pőcze wrote:
> 2026. 03. 13. 12:33 keltezéssel, Jacopo Mondi írta:
> > std::visit() allows quite elegant type-matching implementation of the
> > visitor pattern.
> >
> > The overaloded type helpers allow to define a hierarchy of overloaded
>      '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 types to
>                                                     type
>
>
> > libcamera::utils for easier re-use.
> >
> > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> > ---
> >   include/libcamera/base/utils.h             |  7 ++++++
> >   src/libcamera/base/utils.cpp               | 35 ++++++++++++++++++++++++++++++
> >   src/libcamera/pipeline/virtual/virtual.cpp | 10 ++-------
> >   3 files changed, 44 insertions(+), 8 deletions(-)
> >
> > diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h
> > index 7083b7ce9ce9..62c7f89c25a1 100644
> > --- a/include/libcamera/base/utils.h
> > +++ b/include/libcamera/base/utils.h
> > @@ -37,6 +37,13 @@ namespace libcamera {
> >   namespace utils {
> > +template<class... Ts>
> > +struct overloaded : Ts... {
> > +	using Ts::operator()...;
> > +};
> > +template<class... Ts>
> > +overloaded(Ts...) -> overloaded<Ts...>;
> > +
> >   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..a18ca82e8d07 100644
> > --- a/src/libcamera/base/utils.cpp
> > +++ b/src/libcamera/base/utils.cpp
> > @@ -23,6 +23,41 @@ 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
> > + * implementations of \a operator().
> > + */
> > +
> > +/**
> > + * \var <class... Ts> overloaded(Ts...) -> overloaded<Ts...>
>
> This is just a deduction guide. Does doxygen fail if it is not documented? In any case,

It's pretty easy to test: yes, it does
include/libcamera/base/utils.h:45: warning: Member overloaded(Ts...) -> overloaded< Ts... > (function) of namespace libcamera::utils is not documented.

> if documented, I think it should just mention that this is a deduction guide necessary
> for C++17. And the below text should be moved to the documentation of the type itself.
>

I'll move the documentation!

> Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>

Thanks
  j

>
>
> > + * \brief Overloaded visitor class for type-matching std::visit implementations
> > + * \tparam Ts... Template arguments pack of visitor functions
> > + *
> > + * std::visit allows quite elegant type-matching implementation of the visitor
> > + * pattern. An example is provided by the STL 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)
> >
>

Patch
diff mbox series

diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h
index 7083b7ce9ce9..62c7f89c25a1 100644
--- a/include/libcamera/base/utils.h
+++ b/include/libcamera/base/utils.h
@@ -37,6 +37,13 @@  namespace libcamera {
 
 namespace utils {
 
+template<class... Ts>
+struct overloaded : Ts... {
+	using Ts::operator()...;
+};
+template<class... Ts>
+overloaded(Ts...) -> overloaded<Ts...>;
+
 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..a18ca82e8d07 100644
--- a/src/libcamera/base/utils.cpp
+++ b/src/libcamera/base/utils.cpp
@@ -23,6 +23,41 @@  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
+ * implementations of \a operator().
+ */
+
+/**
+ * \var <class... Ts> overloaded(Ts...) -> overloaded<Ts...>
+ * \brief Overloaded visitor class for type-matching std::visit implementations
+ * \tparam Ts... Template arguments pack of visitor functions
+ *
+ * std::visit allows quite elegant type-matching implementation of the visitor
+ * pattern. An example is provided by the STL 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)