[{"id":24203,"web_url":"https://patchwork.libcamera.org/comment/24203/","msgid":"<f09d018a-3cd1-f876-f8ef-94102f633635@ideasonboard.com>","date":"2022-07-28T06:04:23","subject":"Re: [libcamera-devel] [PATCH v5 1/9] libcamera: base: utils:\n\tProvide defopt to simplify std::optional::value_or() usage","submitter":{"id":86,"url":"https://patchwork.libcamera.org/api/people/86/","name":"Umang Jain","email":"umang.jain@ideasonboard.com"},"content":"Hi Laurent,\n\nThank you for the patch.\n\nOn 7/28/22 03:51, Laurent Pinchart via libcamera-devel wrote:\n> The std::optional<T>::value_or(U &&default_value) function returns the\n> contained value if available, or \\a default_value if the std::optional\n> has no value. If the desired default value is a default-constructed T,\n> the obvious option is to call std::optional<T>::value_or(T{}). This\n> approach has two drawbacks:\n>\n> - The \\a default_value T{} is constructed even if the std::optional\n>    instance has a value, which impacts efficiency.\n> - The T{} default constructor needs to be spelled out explicitly in the\n>    value_or() call, leading to long lines if the type is complex.\n>\n> Introduce a defopt variable that solves these issues by providing a\n> value that can be passed to std::optional<T>::value_or() and get\n> implicitly converted to a default-constructed T.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n\nReviewed-by: Umang Jain <umang.jain@ideasonboard.com>\n\n> ---\n>   include/libcamera/base/utils.h | 14 +++++++++\n>   src/libcamera/base/utils.cpp   | 21 +++++++++++++\n>   test/utils.cpp                 | 54 ++++++++++++++++++++++++++++++++++\n>   3 files changed, 89 insertions(+)\n>\n> diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h\n> index cfff05836de7..889bb4a2270e 100644\n> --- a/include/libcamera/base/utils.h\n> +++ b/include/libcamera/base/utils.h\n> @@ -361,6 +361,20 @@ decltype(auto) abs_diff(const T &a, const T &b)\n>   \t\treturn a - b;\n>   }\n>   \n> +namespace details {\n> +\n> +struct defopt_t {\n> +\ttemplate<typename T>\n> +\toperator T() const\n> +\t{\n> +\t\treturn T{};\n> +\t}\n> +};\n> +\n> +} /* namespace details */\n> +\n> +constexpr details::defopt_t defopt;\n> +\n>   } /* namespace utils */\n>   \n>   #ifndef __DOXYGEN__\n> diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp\n> index 6a307940448e..9cd6cb197243 100644\n> --- a/src/libcamera/base/utils.cpp\n> +++ b/src/libcamera/base/utils.cpp\n> @@ -463,6 +463,27 @@ std::string toAscii(const std::string &str)\n>    * \\a b\n>    */\n>   \n> +/**\n> + * \\var defopt\n> + * \\brief Constant used with std::optional::value_or() to create a\n> + * default-constructed object\n> + *\n> + * The std::optional<T>::value_or(U &&default_value) function returns the\n> + * contained value if available, or \\a default_value if the std::optional has no\n> + * value. If the desired default value is a default-constructed T, the obvious\n> + * option is to call std::optional<T>::value_or(T{}). This approach has two\n> + * drawbacks:\n> + *\n> + * * The \\a default_value T{} is constructed even if the std::optional instance\n> + *   has a value, which impacts efficiency.\n> + * * The T{} default constructor needs to be spelled out explicitly in the\n> + *   value_or() call, leading to long lines if the type is complex.\n> + *\n> + * The defopt variable solves these issues by providing a value that can be\n> + * passed to std::optional<T>::value_or() and get implicitly converted to a\n> + * default-constructed T.\n> + */\n> +\n>   } /* namespace utils */\n>   \n>   #ifndef __DOXYGEN__\n> diff --git a/test/utils.cpp b/test/utils.cpp\n> index d65467b5102c..129807a63ec6 100644\n> --- a/test/utils.cpp\n> +++ b/test/utils.cpp\n> @@ -7,6 +7,7 @@\n>   \n>   #include <iostream>\n>   #include <map>\n> +#include <optional>\n>   #include <sstream>\n>   #include <string>\n>   #include <vector>\n> @@ -169,6 +170,55 @@ protected:\n>   \t\treturn TestPass;\n>   \t}\n>   \n> +\tint testDefopt()\n> +\t{\n> +\t\tstatic bool defaultConstructed = false;\n> +\n> +\t\tstruct ValueType {\n> +\t\t\tValueType()\n> +\t\t\t\t: value_(-1)\n> +\t\t\t{\n> +\t\t\t\tdefaultConstructed = true;\n> +\t\t\t}\n> +\n> +\t\t\tValueType(int value)\n> +\t\t\t\t: value_(value)\n> +\t\t\t{\n> +\t\t\t}\n> +\n> +\t\t\tint value_;\n> +\t\t};\n> +\n> +\t\t/*\n> +\t\t * Test that utils::defopt doesn't cause default-construction\n> +\t\t * of a ValueType instance when value_or(utils::defopt) is\n> +\t\t * called on a std::optional that has a value.\n> +\t\t */\n> +\t\tstd::optional<ValueType> opt = ValueType(0);\n> +\t\tValueType value = opt.value_or(utils::defopt);\n> +\n> +\t\tif (defaultConstructed || value.value_ != 0) {\n> +\t\t\tstd::cerr << \"utils::defopt didn't prevent default construction\"\n> +\t\t\t\t  << std::endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\t/*\n> +\t\t * Then test that the ValueType is correctly default-constructed\n> +\t\t * when the std::optional has no value.\n> +\t\t */\n> +\t\topt = std::nullopt;\n> +\t\tvalue = opt.value_or(utils::defopt);\n> +\n> +\t\tif (!defaultConstructed || value.value_ != -1) {\n> +\t\t\tstd::cerr << \"utils::defopt didn't cause default construction\"\n> +\t\t\t\t  << std::endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\treturn TestPass;\n> +\t}\n> +\n>   \tint run()\n>   \t{\n>   \t\t/* utils::hex() test. */\n> @@ -281,6 +331,10 @@ protected:\n>   \t\tif (testDuration() != TestPass)\n>   \t\t\treturn TestFail;\n>   \n> +\t\t/* utils::defopt test. */\n> +\t\tif (testDefopt() != TestPass)\n> +\t\t\treturn TestFail;\n> +\n>   \t\treturn TestPass;\n>   \t}\n>   };","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 42CA5BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 28 Jul 2022 06:04:32 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7BA0563311;\n\tThu, 28 Jul 2022 08:04:31 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D7D67603E7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 28 Jul 2022 08:04:29 +0200 (CEST)","from [IPV6:2401:4900:1f3e:f7a:bc8f:12ed:b45f:c35d] (unknown\n\t[IPv6:2401:4900:1f3e:f7a:bc8f:12ed:b45f:c35d])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id AB2E78AF;\n\tThu, 28 Jul 2022 08:04:28 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1658988271;\n\tbh=ooN3lO851SKjTVbQ6KcJzkvSl4E8Tm5YY31M9WngEtE=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=MLLtuGfqEmbG+0dcm3+/fCNUZglNbUJBPgbl31AVXXpO6klJAg0Wki8uXF95Wzwwj\n\tj89MUYWujplhSqsx01p0Fw+nGKPpHajVZtBsCuMdMwt8g90o1Dcpxk8QANqZAu9X8D\n\t0L/oBfhcL/7dXLNRlYx4XDCR1Y+dCeBs0RSx1iNHBaUhEqXG626iBsUY69bLbhbTzv\n\toMLWM4V4sXHxKUjdMCwh9i1/aZDaCLUfy1sUOB5Sb63kdVW7b/HcEYyTX110z7r/98\n\tIQfcWo+AwYs8mslx7UwBZrMjw4bvHYDx7gGNG4xnhhF2YtLG+N3DS2eZWVNE88aBL3\n\tAf3K0QcxqWsrw==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1658988269;\n\tbh=ooN3lO851SKjTVbQ6KcJzkvSl4E8Tm5YY31M9WngEtE=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=IBrdFuzzTlQOOAD+XGqADbzYg2aKJnjLiB6TxQGuLxxmVeoQ0dop6murPOi1L59hH\n\to7oU1frqCHZiyNpeS9vZJS1Ns/8wjgOssifqQk2tF/vkQpB+UchboAxhwCQpbSsOg+\n\tjpzK5mLcO3Q/u9ip4OFCfRW2ORoRyZAqoMsRwuK4="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"IBrdFuzz\"; dkim-atps=neutral","Message-ID":"<f09d018a-3cd1-f876-f8ef-94102f633635@ideasonboard.com>","Date":"Thu, 28 Jul 2022 11:34:23 +0530","MIME-Version":"1.0","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101\n\tThunderbird/91.4.1","Content-Language":"en-US","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20220727222149.30627-1-laurent.pinchart@ideasonboard.com>\n\t<20220727222149.30627-2-laurent.pinchart@ideasonboard.com>","In-Reply-To":"<20220727222149.30627-2-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","Subject":"Re: [libcamera-devel] [PATCH v5 1/9] libcamera: base: utils:\n\tProvide defopt to simplify std::optional::value_or() usage","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Umang Jain via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Umang Jain <umang.jain@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":24204,"web_url":"https://patchwork.libcamera.org/comment/24204/","msgid":"<20220728064705.3pxw7ndxo3dgia7u@uno.localdomain>","date":"2022-07-28T06:47:05","subject":"Re: [libcamera-devel] [PATCH v5 1/9] libcamera: base: utils:\n\tProvide defopt to simplify std::optional::value_or() usage","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent\n\nOn Thu, Jul 28, 2022 at 01:21:41AM +0300, Laurent Pinchart via libcamera-devel wrote:\n> The std::optional<T>::value_or(U &&default_value) function returns the\n> contained value if available, or \\a default_value if the std::optional\n\nAre the \\a in the commit message intended ?\n\n> has no value. If the desired default value is a default-constructed T,\n> the obvious option is to call std::optional<T>::value_or(T{}). This\n> approach has two drawbacks:\n>\n> - The \\a default_value T{} is constructed even if the std::optional\n>   instance has a value, which impacts efficiency.\n> - The T{} default constructor needs to be spelled out explicitly in the\n>   value_or() call, leading to long lines if the type is complex.\n>\n> Introduce a defopt variable that solves these issues by providing a\n> value that can be passed to std::optional<T>::value_or() and get\n> implicitly converted to a default-constructed T.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  include/libcamera/base/utils.h | 14 +++++++++\n>  src/libcamera/base/utils.cpp   | 21 +++++++++++++\n>  test/utils.cpp                 | 54 ++++++++++++++++++++++++++++++++++\n>  3 files changed, 89 insertions(+)\n>\n> diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h\n> index cfff05836de7..889bb4a2270e 100644\n> --- a/include/libcamera/base/utils.h\n> +++ b/include/libcamera/base/utils.h\n> @@ -361,6 +361,20 @@ decltype(auto) abs_diff(const T &a, const T &b)\n>  \t\treturn a - b;\n>  }\n>\n> +namespace details {\n> +\n> +struct defopt_t {\n> +\ttemplate<typename T>\n> +\toperator T() const\n> +\t{\n> +\t\treturn T{};\n> +\t}\n> +};\n> +\n> +} /* namespace details */\n> +\n> +constexpr details::defopt_t defopt;\n> +\n\nClever! this indeed explains how it works:\n\ntemplate< class U >\nconstexpr T value_or( U&& default_value ) const&;\n\nEquivalent to bool(*this) ? **this : static_cast<T>(std::forward<U>(default_value))\n\n\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nThanks\n  j\n\n>  } /* namespace utils */\n>\n>  #ifndef __DOXYGEN__\n> diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp\n> index 6a307940448e..9cd6cb197243 100644\n> --- a/src/libcamera/base/utils.cpp\n> +++ b/src/libcamera/base/utils.cpp\n> @@ -463,6 +463,27 @@ std::string toAscii(const std::string &str)\n>   * \\a b\n>   */\n>\n> +/**\n> + * \\var defopt\n> + * \\brief Constant used with std::optional::value_or() to create a\n> + * default-constructed object\n> + *\n> + * The std::optional<T>::value_or(U &&default_value) function returns the\n> + * contained value if available, or \\a default_value if the std::optional has no\n> + * value. If the desired default value is a default-constructed T, the obvious\n> + * option is to call std::optional<T>::value_or(T{}). This approach has two\n> + * drawbacks:\n> + *\n> + * * The \\a default_value T{} is constructed even if the std::optional instance\n> + *   has a value, which impacts efficiency.\n> + * * The T{} default constructor needs to be spelled out explicitly in the\n> + *   value_or() call, leading to long lines if the type is complex.\n> + *\n> + * The defopt variable solves these issues by providing a value that can be\n> + * passed to std::optional<T>::value_or() and get implicitly converted to a\n> + * default-constructed T.\n> + */\n> +\n>  } /* namespace utils */\n>\n>  #ifndef __DOXYGEN__\n> diff --git a/test/utils.cpp b/test/utils.cpp\n> index d65467b5102c..129807a63ec6 100644\n> --- a/test/utils.cpp\n> +++ b/test/utils.cpp\n> @@ -7,6 +7,7 @@\n>\n>  #include <iostream>\n>  #include <map>\n> +#include <optional>\n>  #include <sstream>\n>  #include <string>\n>  #include <vector>\n> @@ -169,6 +170,55 @@ protected:\n>  \t\treturn TestPass;\n>  \t}\n>\n> +\tint testDefopt()\n> +\t{\n> +\t\tstatic bool defaultConstructed = false;\n> +\n> +\t\tstruct ValueType {\n> +\t\t\tValueType()\n> +\t\t\t\t: value_(-1)\n> +\t\t\t{\n> +\t\t\t\tdefaultConstructed = true;\n> +\t\t\t}\n> +\n> +\t\t\tValueType(int value)\n> +\t\t\t\t: value_(value)\n> +\t\t\t{\n> +\t\t\t}\n> +\n> +\t\t\tint value_;\n> +\t\t};\n> +\n> +\t\t/*\n> +\t\t * Test that utils::defopt doesn't cause default-construction\n> +\t\t * of a ValueType instance when value_or(utils::defopt) is\n> +\t\t * called on a std::optional that has a value.\n> +\t\t */\n> +\t\tstd::optional<ValueType> opt = ValueType(0);\n> +\t\tValueType value = opt.value_or(utils::defopt);\n> +\n> +\t\tif (defaultConstructed || value.value_ != 0) {\n> +\t\t\tstd::cerr << \"utils::defopt didn't prevent default construction\"\n> +\t\t\t\t  << std::endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\t/*\n> +\t\t * Then test that the ValueType is correctly default-constructed\n> +\t\t * when the std::optional has no value.\n> +\t\t */\n> +\t\topt = std::nullopt;\n> +\t\tvalue = opt.value_or(utils::defopt);\n> +\n> +\t\tif (!defaultConstructed || value.value_ != -1) {\n> +\t\t\tstd::cerr << \"utils::defopt didn't cause default construction\"\n> +\t\t\t\t  << std::endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\treturn TestPass;\n> +\t}\n> +\n>  \tint run()\n>  \t{\n>  \t\t/* utils::hex() test. */\n> @@ -281,6 +331,10 @@ protected:\n>  \t\tif (testDuration() != TestPass)\n>  \t\t\treturn TestFail;\n>\n> +\t\t/* utils::defopt test. */\n> +\t\tif (testDefopt() != TestPass)\n> +\t\t\treturn TestFail;\n> +\n>  \t\treturn TestPass;\n>  \t}\n>  };\n> --\n> Regards,\n>\n> Laurent Pinchart\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CC0ECC3275\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 28 Jul 2022 06:47:14 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2B36363311;\n\tThu, 28 Jul 2022 08:47:14 +0200 (CEST)","from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net\n\t[IPv6:2001:4b98:dc4:8::223])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C879A603E7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 28 Jul 2022 08:47:12 +0200 (CEST)","(Authenticated sender: jacopo@jmondi.org)\n\tby mail.gandi.net (Postfix) with ESMTPSA id 9641360006;\n\tThu, 28 Jul 2022 06:47:10 +0000 (UTC)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1658990834;\n\tbh=d0uPRpteM/+XxhxSfIy8I//MxcqVtJiMDKmo6fmlQmM=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=GENEzYmd4wNbVd0qrVrE9pVLbRneJvzxXX29pBgOB9AhlbJOc/8LFxIUgWq66mSYV\n\tk8oiYHpF74bsVAof3kqDpDT5b2qziurHS4hz7nwD6L2VJlN7zWRlZHsJMECBEgd758\n\txKMosrzNBiIEZbmM7iWcth0HnN5DiD4UyHzkurDcJslt65tDZwOlr8RWWdGUd3Pgd4\n\tyMNf8k2DRYtluro1f6UzxUZceWhQWACOKf/2NajKRjUF6PwtW5ZO/mD71NAg9q7lbf\n\txJrDG+tOPAb9WUt4jLr3znreUU1NOcF4+nip7NzAbbn6fYQP6orq1ZZ2mGlxQPpb20\n\tZaDO3NTeLtlGQ==","Date":"Thu, 28 Jul 2022 08:47:05 +0200","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Message-ID":"<20220728064705.3pxw7ndxo3dgia7u@uno.localdomain>","References":"<20220727222149.30627-1-laurent.pinchart@ideasonboard.com>\n\t<20220727222149.30627-2-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20220727222149.30627-2-laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v5 1/9] libcamera: base: utils:\n\tProvide defopt to simplify std::optional::value_or() usage","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Jacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":24216,"web_url":"https://patchwork.libcamera.org/comment/24216/","msgid":"<YuJlWILtBE8Fb1Jo@pendragon.ideasonboard.com>","date":"2022-07-28T10:30:48","subject":"Re: [libcamera-devel] [PATCH v5 1/9] libcamera: base: utils:\n\tProvide defopt to simplify std::optional::value_or() usage","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Thu, Jul 28, 2022 at 08:47:05AM +0200, Jacopo Mondi wrote:\n> Hi Laurent\n> \n> On Thu, Jul 28, 2022 at 01:21:41AM +0300, Laurent Pinchart via libcamera-devel wrote:\n> > The std::optional<T>::value_or(U &&default_value) function returns the\n> > contained value if available, or \\a default_value if the std::optional\n> \n> Are the \\a in the commit message intended ?\n\nOops :-) I'll drop it.\n\n> > has no value. If the desired default value is a default-constructed T,\n> > the obvious option is to call std::optional<T>::value_or(T{}). This\n> > approach has two drawbacks:\n> >\n> > - The \\a default_value T{} is constructed even if the std::optional\n> >   instance has a value, which impacts efficiency.\n> > - The T{} default constructor needs to be spelled out explicitly in the\n> >   value_or() call, leading to long lines if the type is complex.\n> >\n> > Introduce a defopt variable that solves these issues by providing a\n> > value that can be passed to std::optional<T>::value_or() and get\n> > implicitly converted to a default-constructed T.\n> >\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  include/libcamera/base/utils.h | 14 +++++++++\n> >  src/libcamera/base/utils.cpp   | 21 +++++++++++++\n> >  test/utils.cpp                 | 54 ++++++++++++++++++++++++++++++++++\n> >  3 files changed, 89 insertions(+)\n> >\n> > diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h\n> > index cfff05836de7..889bb4a2270e 100644\n> > --- a/include/libcamera/base/utils.h\n> > +++ b/include/libcamera/base/utils.h\n> > @@ -361,6 +361,20 @@ decltype(auto) abs_diff(const T &a, const T &b)\n> >  \t\treturn a - b;\n> >  }\n> >\n> > +namespace details {\n> > +\n> > +struct defopt_t {\n> > +\ttemplate<typename T>\n> > +\toperator T() const\n> > +\t{\n> > +\t\treturn T{};\n> > +\t}\n> > +};\n> > +\n> > +} /* namespace details */\n> > +\n> > +constexpr details::defopt_t defopt;\n> > +\n> \n> Clever! this indeed explains how it works:\n> \n> template< class U >\n> constexpr T value_or( U&& default_value ) const&;\n> \n> Equivalent to bool(*this) ? **this : static_cast<T>(std::forward<U>(default_value))\n> \n> \n> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n> \n> >  } /* namespace utils */\n> >\n> >  #ifndef __DOXYGEN__\n> > diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp\n> > index 6a307940448e..9cd6cb197243 100644\n> > --- a/src/libcamera/base/utils.cpp\n> > +++ b/src/libcamera/base/utils.cpp\n> > @@ -463,6 +463,27 @@ std::string toAscii(const std::string &str)\n> >   * \\a b\n> >   */\n> >\n> > +/**\n> > + * \\var defopt\n> > + * \\brief Constant used with std::optional::value_or() to create a\n> > + * default-constructed object\n> > + *\n> > + * The std::optional<T>::value_or(U &&default_value) function returns the\n> > + * contained value if available, or \\a default_value if the std::optional has no\n> > + * value. If the desired default value is a default-constructed T, the obvious\n> > + * option is to call std::optional<T>::value_or(T{}). This approach has two\n> > + * drawbacks:\n> > + *\n> > + * * The \\a default_value T{} is constructed even if the std::optional instance\n> > + *   has a value, which impacts efficiency.\n> > + * * The T{} default constructor needs to be spelled out explicitly in the\n> > + *   value_or() call, leading to long lines if the type is complex.\n> > + *\n> > + * The defopt variable solves these issues by providing a value that can be\n> > + * passed to std::optional<T>::value_or() and get implicitly converted to a\n> > + * default-constructed T.\n> > + */\n> > +\n> >  } /* namespace utils */\n> >\n> >  #ifndef __DOXYGEN__\n> > diff --git a/test/utils.cpp b/test/utils.cpp\n> > index d65467b5102c..129807a63ec6 100644\n> > --- a/test/utils.cpp\n> > +++ b/test/utils.cpp\n> > @@ -7,6 +7,7 @@\n> >\n> >  #include <iostream>\n> >  #include <map>\n> > +#include <optional>\n> >  #include <sstream>\n> >  #include <string>\n> >  #include <vector>\n> > @@ -169,6 +170,55 @@ protected:\n> >  \t\treturn TestPass;\n> >  \t}\n> >\n> > +\tint testDefopt()\n> > +\t{\n> > +\t\tstatic bool defaultConstructed = false;\n> > +\n> > +\t\tstruct ValueType {\n> > +\t\t\tValueType()\n> > +\t\t\t\t: value_(-1)\n> > +\t\t\t{\n> > +\t\t\t\tdefaultConstructed = true;\n> > +\t\t\t}\n> > +\n> > +\t\t\tValueType(int value)\n> > +\t\t\t\t: value_(value)\n> > +\t\t\t{\n> > +\t\t\t}\n> > +\n> > +\t\t\tint value_;\n> > +\t\t};\n> > +\n> > +\t\t/*\n> > +\t\t * Test that utils::defopt doesn't cause default-construction\n> > +\t\t * of a ValueType instance when value_or(utils::defopt) is\n> > +\t\t * called on a std::optional that has a value.\n> > +\t\t */\n> > +\t\tstd::optional<ValueType> opt = ValueType(0);\n> > +\t\tValueType value = opt.value_or(utils::defopt);\n> > +\n> > +\t\tif (defaultConstructed || value.value_ != 0) {\n> > +\t\t\tstd::cerr << \"utils::defopt didn't prevent default construction\"\n> > +\t\t\t\t  << std::endl;\n> > +\t\t\treturn TestFail;\n> > +\t\t}\n> > +\n> > +\t\t/*\n> > +\t\t * Then test that the ValueType is correctly default-constructed\n> > +\t\t * when the std::optional has no value.\n> > +\t\t */\n> > +\t\topt = std::nullopt;\n> > +\t\tvalue = opt.value_or(utils::defopt);\n> > +\n> > +\t\tif (!defaultConstructed || value.value_ != -1) {\n> > +\t\t\tstd::cerr << \"utils::defopt didn't cause default construction\"\n> > +\t\t\t\t  << std::endl;\n> > +\t\t\treturn TestFail;\n> > +\t\t}\n> > +\n> > +\t\treturn TestPass;\n> > +\t}\n> > +\n> >  \tint run()\n> >  \t{\n> >  \t\t/* utils::hex() test. */\n> > @@ -281,6 +331,10 @@ protected:\n> >  \t\tif (testDuration() != TestPass)\n> >  \t\t\treturn TestFail;\n> >\n> > +\t\t/* utils::defopt test. */\n> > +\t\tif (testDefopt() != TestPass)\n> > +\t\t\treturn TestFail;\n> > +\n> >  \t\treturn TestPass;\n> >  \t}\n> >  };","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E3219C3275\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 28 Jul 2022 10:30:52 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A099E63312;\n\tThu, 28 Jul 2022 12:30:52 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7A3096330D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 28 Jul 2022 12:30:51 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id DBF5656D;\n\tThu, 28 Jul 2022 12:30:50 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1659004252;\n\tbh=KfwwjNMZr2XoDAWKAS+Kv8EfpOyuoKA5U8OwlOQ/5Yg=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=L68Lc3W4Wqw2kPlRo2GZFgEXCVynBjo8ZvoQ8QhEWCM/fVoNFAWF2mlTo5oEYBnhr\n\tXcfZ425fQGZ112a35Dgrv1z0wrnACG+D/B2/1SHH7c7f7VIE8glg3N6/Y0GOjBoPAG\n\tIRwKt1KrLIhz5s34T0R/h1QkUDNbf3zN0YIATLKXfKX6IFXu9pK0mrqAkNc+Ash6Y+\n\tsIh+hdJak6vwZgFfM1w6jC09XP1QWe0iHMfHnQOtDoHHJVxDEhf4hpzxeRnRiVqafH\n\tunhOXASwzY7KTlOhW+Z3EnOHY/1S38zd0vm1wBEVmCn//VOvAlD/LWzvDZnrraUZ/a\n\t/sykN7gaMYHKg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1659004251;\n\tbh=KfwwjNMZr2XoDAWKAS+Kv8EfpOyuoKA5U8OwlOQ/5Yg=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=LoY9hVYsqjoCBTGBxsPORjVowg20tSkDlBY0xmAHL3N9cvCnn/KRlTU4RgxdmdRMA\n\tTC+OWzQcteTnr/oEhS1VJkCLLcz4U2pRkoNzfKSuwIjxIPAf+Z/q42rnBdLL0nqu/Z\n\tZWJ3UopP8go79liTKikMOp5wHuZGx6n+ySfgygUQ="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"LoY9hVYs\"; dkim-atps=neutral","Date":"Thu, 28 Jul 2022 13:30:48 +0300","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<YuJlWILtBE8Fb1Jo@pendragon.ideasonboard.com>","References":"<20220727222149.30627-1-laurent.pinchart@ideasonboard.com>\n\t<20220727222149.30627-2-laurent.pinchart@ideasonboard.com>\n\t<20220728064705.3pxw7ndxo3dgia7u@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20220728064705.3pxw7ndxo3dgia7u@uno.localdomain>","Subject":"Re: [libcamera-devel] [PATCH v5 1/9] libcamera: base: utils:\n\tProvide defopt to simplify std::optional::value_or() usage","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":24236,"web_url":"https://patchwork.libcamera.org/comment/24236/","msgid":"<CALzBHU7etD2H_Pi95SrcRQvF+aysB+o=L6E2_KcfRbQtrbue7A@mail.gmail.com>","date":"2022-07-29T07:10:21","subject":"Re: [libcamera-devel] [PATCH v5 1/9] libcamera: base: utils:\n\tProvide defopt to simplify std::optional::value_or() usage","submitter":{"id":123,"url":"https://patchwork.libcamera.org/api/people/123/","name":"Florian Sylvestre","email":"fsylvestre@baylibre.com"},"content":"Hi Laurent,\n\nOn Thu, 28 Jul 2022 at 12:30, Laurent Pinchart via libcamera-devel\n<libcamera-devel@lists.libcamera.org> wrote:\n>\n> Hi Jacopo,\n>\n> On Thu, Jul 28, 2022 at 08:47:05AM +0200, Jacopo Mondi wrote:\n> > Hi Laurent\n> >\n> > On Thu, Jul 28, 2022 at 01:21:41AM +0300, Laurent Pinchart via libcamera-devel wrote:\n> > > The std::optional<T>::value_or(U &&default_value) function returns the\n> > > contained value if available, or \\a default_value if the std::optional\n> >\n> > Are the \\a in the commit message intended ?\n>\n> Oops :-) I'll drop it.\n>\n> > > has no value. If the desired default value is a default-constructed T,\n> > > the obvious option is to call std::optional<T>::value_or(T{}). This\n> > > approach has two drawbacks:\n> > >\n> > > - The \\a default_value T{} is constructed even if the std::optional\n> > >   instance has a value, which impacts efficiency.\n> > > - The T{} default constructor needs to be spelled out explicitly in the\n> > >   value_or() call, leading to long lines if the type is complex.\n> > >\n> > > Introduce a defopt variable that solves these issues by providing a\n> > > value that can be passed to std::optional<T>::value_or() and get\n> > > implicitly converted to a default-constructed T.\n> > >\n> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > > ---\n> > >  include/libcamera/base/utils.h | 14 +++++++++\n> > >  src/libcamera/base/utils.cpp   | 21 +++++++++++++\n> > >  test/utils.cpp                 | 54 ++++++++++++++++++++++++++++++++++\n> > >  3 files changed, 89 insertions(+)\n> > >\n> > > diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h\n> > > index cfff05836de7..889bb4a2270e 100644\n> > > --- a/include/libcamera/base/utils.h\n> > > +++ b/include/libcamera/base/utils.h\n> > > @@ -361,6 +361,20 @@ decltype(auto) abs_diff(const T &a, const T &b)\n> > >             return a - b;\n> > >  }\n> > >\n> > > +namespace details {\n> > > +\n> > > +struct defopt_t {\n> > > +   template<typename T>\n> > > +   operator T() const\n> > > +   {\n> > > +           return T{};\n> > > +   }\n> > > +};\n> > > +\n> > > +} /* namespace details */\n> > > +\n> > > +constexpr details::defopt_t defopt;\n> > > +\n> >\n> > Clever! this indeed explains how it works:\n> >\n> > template< class U >\n> > constexpr T value_or( U&& default_value ) const&;\n> >\n> > Equivalent to bool(*this) ? **this : static_cast<T>(std::forward<U>(default_value))\n> >\n> >\n> > Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n> >\n> > >  } /* namespace utils */\n> > >\n> > >  #ifndef __DOXYGEN__\n> > > diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp\n> > > index 6a307940448e..9cd6cb197243 100644\n> > > --- a/src/libcamera/base/utils.cpp\n> > > +++ b/src/libcamera/base/utils.cpp\n> > > @@ -463,6 +463,27 @@ std::string toAscii(const std::string &str)\n> > >   * \\a b\n> > >   */\n> > >\n> > > +/**\n> > > + * \\var defopt\n> > > + * \\brief Constant used with std::optional::value_or() to create a\n> > > + * default-constructed object\n> > > + *\n> > > + * The std::optional<T>::value_or(U &&default_value) function returns the\n> > > + * contained value if available, or \\a default_value if the std::optional has no\n> > > + * value. If the desired default value is a default-constructed T, the obvious\n> > > + * option is to call std::optional<T>::value_or(T{}). This approach has two\n> > > + * drawbacks:\n> > > + *\n> > > + * * The \\a default_value T{} is constructed even if the std::optional instance\n> > > + *   has a value, which impacts efficiency.\n> > > + * * The T{} default constructor needs to be spelled out explicitly in the\n> > > + *   value_or() call, leading to long lines if the type is complex.\n> > > + *\n> > > + * The defopt variable solves these issues by providing a value that can be\n> > > + * passed to std::optional<T>::value_or() and get implicitly converted to a\n> > > + * default-constructed T.\n> > > + */\n> > > +\n> > >  } /* namespace utils */\n> > >\n> > >  #ifndef __DOXYGEN__\n> > > diff --git a/test/utils.cpp b/test/utils.cpp\n> > > index d65467b5102c..129807a63ec6 100644\n> > > --- a/test/utils.cpp\n> > > +++ b/test/utils.cpp\n> > > @@ -7,6 +7,7 @@\n> > >\n> > >  #include <iostream>\n> > >  #include <map>\n> > > +#include <optional>\n> > >  #include <sstream>\n> > >  #include <string>\n> > >  #include <vector>\n> > > @@ -169,6 +170,55 @@ protected:\n> > >             return TestPass;\n> > >     }\n> > >\n> > > +   int testDefopt()\n> > > +   {\n> > > +           static bool defaultConstructed = false;\n> > > +\n> > > +           struct ValueType {\n> > > +                   ValueType()\n> > > +                           : value_(-1)\n> > > +                   {\n> > > +                           defaultConstructed = true;\n> > > +                   }\n> > > +\n> > > +                   ValueType(int value)\n> > > +                           : value_(value)\n> > > +                   {\n> > > +                   }\n> > > +\n> > > +                   int value_;\n> > > +           };\n> > > +\n> > > +           /*\n> > > +            * Test that utils::defopt doesn't cause default-construction\n> > > +            * of a ValueType instance when value_or(utils::defopt) is\n> > > +            * called on a std::optional that has a value.\n> > > +            */\n> > > +           std::optional<ValueType> opt = ValueType(0);\n> > > +           ValueType value = opt.value_or(utils::defopt);\n> > > +\n> > > +           if (defaultConstructed || value.value_ != 0) {\n> > > +                   std::cerr << \"utils::defopt didn't prevent default construction\"\n> > > +                             << std::endl;\n> > > +                   return TestFail;\n> > > +           }\n> > > +\n> > > +           /*\n> > > +            * Then test that the ValueType is correctly default-constructed\n> > > +            * when the std::optional has no value.\n> > > +            */\n> > > +           opt = std::nullopt;\n> > > +           value = opt.value_or(utils::defopt);\n> > > +\n> > > +           if (!defaultConstructed || value.value_ != -1) {\n> > > +                   std::cerr << \"utils::defopt didn't cause default construction\"\n> > > +                             << std::endl;\n> > > +                   return TestFail;\n> > > +           }\n> > > +\n> > > +           return TestPass;\n> > > +   }\n> > > +\n> > >     int run()\n> > >     {\n> > >             /* utils::hex() test. */\n> > > @@ -281,6 +331,10 @@ protected:\n> > >             if (testDuration() != TestPass)\n> > >                     return TestFail;\n> > >\n> > > +           /* utils::defopt test. */\n> > > +           if (testDefopt() != TestPass)\n> > > +                   return TestFail;\n> > > +\n> > >             return TestPass;\n> > >     }\n> > >  };\n>\n> --\n> Regards,\n>\n> Laurent Pinchart\n\nReviewed-by: Florian Sylvestre <fsylvestre@baylibre.com>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 4DAB7C3275\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 29 Jul 2022 07:10:37 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A932263312;\n\tFri, 29 Jul 2022 09:10:36 +0200 (CEST)","from mail-pl1-x635.google.com (mail-pl1-x635.google.com\n\t[IPv6:2607:f8b0:4864:20::635])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A50F360486\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 29 Jul 2022 09:10:34 +0200 (CEST)","by mail-pl1-x635.google.com with SMTP id o3so3839927ple.5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 29 Jul 2022 00:10:34 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1659078636;\n\tbh=ggRv9A3BYow7n2f+0Tw9gqWEx733rxXnkcohfEkLPdk=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=PT5je3aXaIayQlSp1yWMSWuIcf8ZwKkSZtth2dP51GG7AmCVOGS7Sgwy7rmtjQiGs\n\tqu8n4WxEtHndtwlT99CgGS0tvUXttCQqw68SdcSFxa0LdGpadSF9jboQriPkpnWkDM\n\tretPfgujpp65vhgZlRL0hka68JMwBN8OEf30rB2RIAZPe8DSPZvJSPhHV4JFUZ0+2P\n\tNPEgg8e+HiVfBjrhtdl+OVB3eUkeG56zYkvBNwArzOOQVy9FT0+4L+rg1KoZAGYIDo\n\tR56PMmC7O1XEnKTUbmhVov4BdTeIUNvh2L7Nsz4CzObKZ0KLm03N8vxCEfdYpba46p\n\tm4xLitwqRWCuQ==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=baylibre-com.20210112.gappssmtp.com; s=20210112;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc; bh=OKSwDZXLx8QeGIKiongGbvsw6Hpq8+nFpVL37HkN2dM=;\n\tb=JbVIUiXRoo2+hKicvrXmT7naaf873fPAFwX+AX39DMjxtQubkoWtt0VSps9a2EIhcr\n\t8Lm710Ds9qJaRng88FnJPNDgKL0sZTvYBiDiXKQcDNxDzhIKxkP2MkZMXcWUW7xKgxzl\n\trKfEq8vkNg7j72/9PJ78jUoUQH9Zh0jWlCET2loyPhNpLf+FA9pQr0KR9RKSeqL4pDY3\n\tS/W41weqOycLgcq9VETJCygbrtt/YZp5Mtk1glBmweifSx62uxRCh40du74ty4vWlcEb\n\tO2Kor6U3ewXln2sUgnmCIBOnHLH9jm6t+Tjdcfv+zRKHfe98MV+bAXkgojx7+OPWHjTP\n\tvUdw=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected)\n\theader.d=baylibre-com.20210112.gappssmtp.com\n\theader.i=@baylibre-com.20210112.gappssmtp.com header.b=\"JbVIUiXR\"; \n\tdkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc;\n\tbh=OKSwDZXLx8QeGIKiongGbvsw6Hpq8+nFpVL37HkN2dM=;\n\tb=hQ+b83nhq5zoYCJu/QkqAWh8Z//EaE0zacrED6UpxE0ZiZwAI02eahcfYT0PpDbmDU\n\tJZNm+kRIePb2uNChWrXgMtK+K7tv69v/jPmPkWzQPDGNWoUfqgQlwExptfsrsTQm7/MP\n\tWkQ4Toaql9Ye3livss8vc8wToWWk/C0RRz6po+UCrdl/PO5rdAu5NAz7MGK4qosZh1Vv\n\tMSFABD3XHhAbifz9zHx3+Ue2H/AJbAi3GYSUTGzxlwYmUwnTbJMJc/ZbjHOxOYyIYmee\n\tzjMGw5EQmL9vQ2svldCkX/tML3yEub6KVur28g2sNCSUJRVSYhcD7ihDvj7+KZq+Jmya\n\tt1kw==","X-Gm-Message-State":"ACgBeo3rxKE10koqfy8e9zhh4DCdqQzYOyTc8jzxoyqD7nHm3jZD1nqn\n\tTyTKcQBBNQJsIHEag3MGuYbQUuJj+v3zZzv53aR89QF3jJIC0D54","X-Google-Smtp-Source":"AA6agR6xFik+nDtQ2Tq49eMctjgUqeT9Rb9uJ//YzigaSTNljCyIAB36dhbZ8rBLX0wYjDCY4fMFegszccRHah4b1S8=","X-Received":"by 2002:a17:902:ce0e:b0:16c:7977:9d74 with SMTP id\n\tk14-20020a170902ce0e00b0016c79779d74mr2544354plg.92.1659078632826;\n\tFri, 29 Jul 2022 00:10:32 -0700 (PDT)","MIME-Version":"1.0","References":"<20220727222149.30627-1-laurent.pinchart@ideasonboard.com>\n\t<20220727222149.30627-2-laurent.pinchart@ideasonboard.com>\n\t<20220728064705.3pxw7ndxo3dgia7u@uno.localdomain>\n\t<YuJlWILtBE8Fb1Jo@pendragon.ideasonboard.com>","In-Reply-To":"<YuJlWILtBE8Fb1Jo@pendragon.ideasonboard.com>","Date":"Fri, 29 Jul 2022 09:10:21 +0200","Message-ID":"<CALzBHU7etD2H_Pi95SrcRQvF+aysB+o=L6E2_KcfRbQtrbue7A@mail.gmail.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Subject":"Re: [libcamera-devel] [PATCH v5 1/9] libcamera: base: utils:\n\tProvide defopt to simplify std::optional::value_or() usage","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Florian Sylvestre via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Florian Sylvestre <fsylvestre@baylibre.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]