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

Message ID 20260313-mali-cru-v5-2-48f93e431294@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, 4:14 p.m. UTC
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.

Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
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(-)

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..836aec87c539 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 \a
+ * operator() to support type-matching implementations of the visitor design
+ * pattern using std::visit.
+ *
+ * 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().
+ */
+
+/**
+ * \var <class... Ts> overloaded(Ts...) -> overloaded<Ts...>
+ * \brief Deduction guide necessary for C++17 compatibility
+ * \tparam Ts... Template arguments pack of visitor functions
+ */
+
 /**
  * \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)