[{"id":38847,"web_url":"https://patchwork.libcamera.org/comment/38847/","msgid":"<1607e176-b22e-4ace-a9a1-b38e5f453aeb@ideasonboard.com>","date":"2026-05-11T08:58:27","subject":"Re: [PATCH] libcamera: bound_method: Use std::apply","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"Hi\n\n2026. 05. 09. 0:10 keltezéssel, Laurent Pinchart írta:\n> Now that libcamera uses C++20, we can use std::apply to replace the\n> custom implementation.\n\nAs far as I'm aware `std::apply` is C++17.\n\n\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>   include/libcamera/base/bound_method.h | 13 ++++++-------\n>   1 file changed, 6 insertions(+), 7 deletions(-)\n> \n> diff --git a/include/libcamera/base/bound_method.h b/include/libcamera/base/bound_method.h\n> index 91fe8b8cb969..ad5374f70b18 100644\n> --- a/include/libcamera/base/bound_method.h\n> +++ b/include/libcamera/base/bound_method.h\n> @@ -91,15 +91,14 @@ public:\n>   \tusing PackType = BoundMethodPack<R, Args...>;\n>   \n>   private:\n> -\ttemplate<std::size_t... I>\n> -\tvoid invokePack(BoundMethodPackBase *pack, std::index_sequence<I...>)\n> +\tvoid invokePack(PackType *args)\n>   \t{\n> -\t\t[[maybe_unused]] auto *args = static_cast<PackType *>(pack);\n> -\n>   \t\tif constexpr (!std::is_void_v<R>)\n> -\t\t\targs->ret_ = invoke(std::get<I>(args->args_)...);\n> +\t\t\targs->ret_ = std::apply(&BoundMethodArgs::invoke,\n> +\t\t\t\t\t\tstd::tuple_cat(std::forward_as_tuple(this), args->args_));\n>   \t\telse\n> -\t\t\tinvoke(std::get<I>(args->args_)...);\n> +\t\t\tstd::apply(&BoundMethodArgs::invoke,\n> +\t\t\t\t   std::tuple_cat(std::forward_as_tuple(this), args->args_));\n\nI think `tuple_cat` preserves the types, so since `args_` contains no references, this will\nmake another copy of each argument. If `std::move(args->args_)` is used, that should only\nmove construct the new elements, but even that seems like an unnecessary overhead to me.\n\n\n>   \t}\n>   \n>   public:\n> @@ -108,7 +107,7 @@ public:\n>   \n>   \tvoid invokePack(BoundMethodPackBase *pack) override\n>   \t{\n> -\t\tinvokePack(pack, std::make_index_sequence<sizeof...(Args)>{});\n> +\t\tinvokePack(static_cast<PackType *>(pack));\n\nIf we want to use `std::apply`, I'd inline things here:\n\n   std::apply([&](auto&&... args /* or Args&&... args */) {\n     if constexpr (!std::is_void_v<R>)\n       args->ret_ = invoke(std::forward<decltype(args)>(args)...);\n     else\n       invoke(std::forward<decltype(args)>(args)...);\n   }, std::move(args->args_));\n\n\n\n>   \t}\n>   \n>   \tvirtual R activate(Args... args, bool deleteMethod = false) = 0;\n> \n> base-commit: 2ca75f012fa12621ed70e333e635d173e92593e5","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 01AC6BDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 11 May 2026 08:58:34 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A036A63020;\n\tMon, 11 May 2026 10:58:33 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4B22562010\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 11 May 2026 10:58:32 +0200 (CEST)","from [192.168.33.37] (185.182.215.166.nat.pool.zt.hu\n\t[185.182.215.166])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 47778593;\n\tMon, 11 May 2026 10:58:25 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"AiqIL4FN\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1778489905;\n\tbh=5vnb6mRu2Urfko3uTN05AsBlrbQKp/lSQksXaKPmVK4=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=AiqIL4FN5PlYkDYeJmP03T8SuwvW0gQh5jgVuGDTWF1xYn+DOG9Jk6ZQOfDxAuZtc\n\taqVXeFFCRTjSfirO+TlPy3BWXaED9uCdNWV8Km9jSFMeIYoGclPv+4SZccuACcXQgJ\n\tZlHUyHXMueH2WwISoyWaGAb2MarWv12vHVZpH8wU=","Message-ID":"<1607e176-b22e-4ace-a9a1-b38e5f453aeb@ideasonboard.com>","Date":"Mon, 11 May 2026 10:58:27 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH] libcamera: bound_method: Use std::apply","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20260508221033.2417134-1-laurent.pinchart@ideasonboard.com>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<20260508221033.2417134-1-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38852,"web_url":"https://patchwork.libcamera.org/comment/38852/","msgid":"<20260511102038.GA2990941@killaraus.ideasonboard.com>","date":"2026-05-11T10:20:38","subject":"Re: [PATCH] libcamera: bound_method: Use std::apply","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Mon, May 11, 2026 at 10:58:27AM +0200, Barnabás Pőcze wrote:\n> 2026. 05. 09. 0:10 keltezéssel, Laurent Pinchart írta:\n> > Now that libcamera uses C++20, we can use std::apply to replace the\n> > custom implementation.\n> \n> As far as I'm aware `std::apply` is C++17.\n\nIt is. I've had this patch in my tree for a long time, and the commit\nmessage stated C++17. I replaced it with C++20 before sending it, as\nwe've switched to C++20. I don't mind writing C++17.\n\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >   include/libcamera/base/bound_method.h | 13 ++++++-------\n> >   1 file changed, 6 insertions(+), 7 deletions(-)\n> > \n> > diff --git a/include/libcamera/base/bound_method.h b/include/libcamera/base/bound_method.h\n> > index 91fe8b8cb969..ad5374f70b18 100644\n> > --- a/include/libcamera/base/bound_method.h\n> > +++ b/include/libcamera/base/bound_method.h\n> > @@ -91,15 +91,14 @@ public:\n> >   \tusing PackType = BoundMethodPack<R, Args...>;\n> >   \n> >   private:\n> > -\ttemplate<std::size_t... I>\n> > -\tvoid invokePack(BoundMethodPackBase *pack, std::index_sequence<I...>)\n> > +\tvoid invokePack(PackType *args)\n> >   \t{\n> > -\t\t[[maybe_unused]] auto *args = static_cast<PackType *>(pack);\n> > -\n> >   \t\tif constexpr (!std::is_void_v<R>)\n> > -\t\t\targs->ret_ = invoke(std::get<I>(args->args_)...);\n> > +\t\t\targs->ret_ = std::apply(&BoundMethodArgs::invoke,\n> > +\t\t\t\t\t\tstd::tuple_cat(std::forward_as_tuple(this), args->args_));\n> >   \t\telse\n> > -\t\t\tinvoke(std::get<I>(args->args_)...);\n> > +\t\t\tstd::apply(&BoundMethodArgs::invoke,\n> > +\t\t\t\t   std::tuple_cat(std::forward_as_tuple(this), args->args_));\n> \n> I think `tuple_cat` preserves the types, so since `args_` contains no references, this will\n> make another copy of each argument. If `std::move(args->args_)` is used, that should only\n> move construct the new elements, but even that seems like an unnecessary overhead to me.\n> \n> >   \t}\n> >   \n> >   public:\n> > @@ -108,7 +107,7 @@ public:\n> >   \n> >   \tvoid invokePack(BoundMethodPackBase *pack) override\n> >   \t{\n> > -\t\tinvokePack(pack, std::make_index_sequence<sizeof...(Args)>{});\n> > +\t\tinvokePack(static_cast<PackType *>(pack));\n> \n> If we want to use `std::apply`, I'd inline things here:\n\nAh good point, the private overload of invokePack() isn't needed any\nmore. I'll send a v2.\n\n>    std::apply([&](auto&&... args /* or Args&&... args */) {\n>      if constexpr (!std::is_void_v<R>)\n>        args->ret_ = invoke(std::forward<decltype(args)>(args)...);\n>      else\n>        invoke(std::forward<decltype(args)>(args)...);\n>    }, std::move(args->args_));\n\nThis means the pack can be used once only. It should be fine, as every\nbound method connected to a signal gets its own pack.\n\n> >   \t}\n> >   \n> >   \tvirtual R activate(Args... args, bool deleteMethod = false) = 0;\n> > \n> > base-commit: 2ca75f012fa12621ed70e333e635d173e92593e5","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 B0E46BDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 11 May 2026 10:20:42 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4C79B63025;\n\tMon, 11 May 2026 12:20:41 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 69C0062DC4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 11 May 2026 12:20:40 +0200 (CEST)","from killaraus.ideasonboard.com\n\t(2001-14ba-70f3-e800--a06.rev.dnainternet.fi\n\t[IPv6:2001:14ba:70f3:e800::a06])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 2B4CC244;\n\tMon, 11 May 2026 12:20:33 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"EssuBLWX\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1778494833;\n\tbh=0sdmKXK6j2MmxgkNd4JPeRj+42AF97tyzGBrwCtahQA=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=EssuBLWXKvasfffFCx90NvNCjE/7+FDbMpAd+J18RAMd2AedcaWg6iHb+DzqyLqL4\n\tCUKLcoOxhGPUSqd0n3Qffw7eO9SWAl4hRUCxPB4NfvS6xmHdaRzkenGaMht5he9WEx\n\t+6v3t2uOvggpjlsQ7XGG+GZ3a0Jnnq4K52EiBjps=","Date":"Mon, 11 May 2026 13:20:38 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH] libcamera: bound_method: Use std::apply","Message-ID":"<20260511102038.GA2990941@killaraus.ideasonboard.com>","References":"<20260508221033.2417134-1-laurent.pinchart@ideasonboard.com>\n\t<1607e176-b22e-4ace-a9a1-b38e5f453aeb@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<1607e176-b22e-4ace-a9a1-b38e5f453aeb@ideasonboard.com>","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38853,"web_url":"https://patchwork.libcamera.org/comment/38853/","msgid":"<3479846d-5d1d-45ad-8017-ac2b6810a24f@ideasonboard.com>","date":"2026-05-11T10:24:19","subject":"Re: [PATCH] libcamera: bound_method: Use std::apply","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2026. 05. 11. 12:20 keltezéssel, Laurent Pinchart írta:\n> On Mon, May 11, 2026 at 10:58:27AM +0200, Barnabás Pőcze wrote:\n>> 2026. 05. 09. 0:10 keltezéssel, Laurent Pinchart írta:\n>>> Now that libcamera uses C++20, we can use std::apply to replace the\n>>> custom implementation.\n>>\n>> As far as I'm aware `std::apply` is C++17.\n> \n> It is. I've had this patch in my tree for a long time, and the commit\n> message stated C++17. I replaced it with C++20 before sending it, as\n> we've switched to C++20. I don't mind writing C++17.\n> \n>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n>>> ---\n>>>    include/libcamera/base/bound_method.h | 13 ++++++-------\n>>>    1 file changed, 6 insertions(+), 7 deletions(-)\n>>>\n>>> diff --git a/include/libcamera/base/bound_method.h b/include/libcamera/base/bound_method.h\n>>> index 91fe8b8cb969..ad5374f70b18 100644\n>>> --- a/include/libcamera/base/bound_method.h\n>>> +++ b/include/libcamera/base/bound_method.h\n>>> @@ -91,15 +91,14 @@ public:\n>>>    \tusing PackType = BoundMethodPack<R, Args...>;\n>>>    \n>>>    private:\n>>> -\ttemplate<std::size_t... I>\n>>> -\tvoid invokePack(BoundMethodPackBase *pack, std::index_sequence<I...>)\n>>> +\tvoid invokePack(PackType *args)\n>>>    \t{\n>>> -\t\t[[maybe_unused]] auto *args = static_cast<PackType *>(pack);\n>>> -\n>>>    \t\tif constexpr (!std::is_void_v<R>)\n>>> -\t\t\targs->ret_ = invoke(std::get<I>(args->args_)...);\n>>> +\t\t\targs->ret_ = std::apply(&BoundMethodArgs::invoke,\n>>> +\t\t\t\t\t\tstd::tuple_cat(std::forward_as_tuple(this), args->args_));\n>>>    \t\telse\n>>> -\t\t\tinvoke(std::get<I>(args->args_)...);\n>>> +\t\t\tstd::apply(&BoundMethodArgs::invoke,\n>>> +\t\t\t\t   std::tuple_cat(std::forward_as_tuple(this), args->args_));\n>>\n>> I think `tuple_cat` preserves the types, so since `args_` contains no references, this will\n>> make another copy of each argument. If `std::move(args->args_)` is used, that should only\n>> move construct the new elements, but even that seems like an unnecessary overhead to me.\n>>\n>>>    \t}\n>>>    \n>>>    public:\n>>> @@ -108,7 +107,7 @@ public:\n>>>    \n>>>    \tvoid invokePack(BoundMethodPackBase *pack) override\n>>>    \t{\n>>> -\t\tinvokePack(pack, std::make_index_sequence<sizeof...(Args)>{});\n>>> +\t\tinvokePack(static_cast<PackType *>(pack));\n>>\n>> If we want to use `std::apply`, I'd inline things here:\n> \n> Ah good point, the private overload of invokePack() isn't needed any\n> more. I'll send a v2.\n> \n>>     std::apply([&](auto&&... args /* or Args&&... args */) {\n>>       if constexpr (!std::is_void_v<R>)\n>>         args->ret_ = invoke(std::forward<decltype(args)>(args)...);\n>>       else\n>>         invoke(std::forward<decltype(args)>(args)...);\n>>     }, std::move(args->args_));\n> \n> This means the pack can be used once only. It should be fine, as every\n> bound method connected to a signal gets its own pack.\n\nYes, but I believe we have recently agreed that is fine?\nAt least I have already merged https://patchwork.libcamera.org/patch/26688/\nwhich does effectively the same \"move\".\n\n\n> \n>>>    \t}\n>>>    \n>>>    \tvirtual R activate(Args... args, bool deleteMethod = false) = 0;\n>>>\n>>> base-commit: 2ca75f012fa12621ed70e333e635d173e92593e5\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 159E7BDB1C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 11 May 2026 10:24:26 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C15926301E;\n\tMon, 11 May 2026 12:24:24 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4FC0C62DC4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 11 May 2026 12:24:23 +0200 (CEST)","from [192.168.33.37] (185.182.215.166.nat.pool.zt.hu\n\t[185.182.215.166])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 3D4EE244;\n\tMon, 11 May 2026 12:24:16 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"TzsOu49o\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1778495056;\n\tbh=fsZPkiox4dgtBISUAp58ytcj8400g0q3tD7YPYYCaVg=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=TzsOu49oY59JOse5NfvF41csJ1eqDmcCPfKpSiMxDbWkqlbmGQ9QUVxDuLPBd39GU\n\t+q3jaMM7O3/XJAWKA1LssqRjjVRlMLEamnragPjqt8jh+Cin/puGrM2QqDZvAFHhia\n\tGx9GJkwLnB4yRwDOzGpvtVxJXJfcc8A6w34A/83M=","Message-ID":"<3479846d-5d1d-45ad-8017-ac2b6810a24f@ideasonboard.com>","Date":"Mon, 11 May 2026 12:24:19 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH] libcamera: bound_method: Use std::apply","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","References":"<20260508221033.2417134-1-laurent.pinchart@ideasonboard.com>\n\t<1607e176-b22e-4ace-a9a1-b38e5f453aeb@ideasonboard.com>\n\t<20260511102038.GA2990941@killaraus.ideasonboard.com>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<20260511102038.GA2990941@killaraus.ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":38854,"web_url":"https://patchwork.libcamera.org/comment/38854/","msgid":"<20260511103257.GB2990941@killaraus.ideasonboard.com>","date":"2026-05-11T10:32:57","subject":"Re: [PATCH] libcamera: bound_method: Use std::apply","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Mon, May 11, 2026 at 12:24:19PM +0200, Barnabás Pőcze wrote:\n> 2026. 05. 11. 12:20 keltezéssel, Laurent Pinchart írta:\n> > On Mon, May 11, 2026 at 10:58:27AM +0200, Barnabás Pőcze wrote:\n> >> 2026. 05. 09. 0:10 keltezéssel, Laurent Pinchart írta:\n> >>> Now that libcamera uses C++20, we can use std::apply to replace the\n> >>> custom implementation.\n> >>\n> >> As far as I'm aware `std::apply` is C++17.\n> > \n> > It is. I've had this patch in my tree for a long time, and the commit\n> > message stated C++17. I replaced it with C++20 before sending it, as\n> > we've switched to C++20. I don't mind writing C++17.\n> > \n> >>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> >>> ---\n> >>>    include/libcamera/base/bound_method.h | 13 ++++++-------\n> >>>    1 file changed, 6 insertions(+), 7 deletions(-)\n> >>>\n> >>> diff --git a/include/libcamera/base/bound_method.h b/include/libcamera/base/bound_method.h\n> >>> index 91fe8b8cb969..ad5374f70b18 100644\n> >>> --- a/include/libcamera/base/bound_method.h\n> >>> +++ b/include/libcamera/base/bound_method.h\n> >>> @@ -91,15 +91,14 @@ public:\n> >>>    \tusing PackType = BoundMethodPack<R, Args...>;\n> >>>    \n> >>>    private:\n> >>> -\ttemplate<std::size_t... I>\n> >>> -\tvoid invokePack(BoundMethodPackBase *pack, std::index_sequence<I...>)\n> >>> +\tvoid invokePack(PackType *args)\n> >>>    \t{\n> >>> -\t\t[[maybe_unused]] auto *args = static_cast<PackType *>(pack);\n> >>> -\n> >>>    \t\tif constexpr (!std::is_void_v<R>)\n> >>> -\t\t\targs->ret_ = invoke(std::get<I>(args->args_)...);\n> >>> +\t\t\targs->ret_ = std::apply(&BoundMethodArgs::invoke,\n> >>> +\t\t\t\t\t\tstd::tuple_cat(std::forward_as_tuple(this), args->args_));\n> >>>    \t\telse\n> >>> -\t\t\tinvoke(std::get<I>(args->args_)...);\n> >>> +\t\t\tstd::apply(&BoundMethodArgs::invoke,\n> >>> +\t\t\t\t   std::tuple_cat(std::forward_as_tuple(this), args->args_));\n> >>\n> >> I think `tuple_cat` preserves the types, so since `args_` contains no references, this will\n> >> make another copy of each argument. If `std::move(args->args_)` is used, that should only\n> >> move construct the new elements, but even that seems like an unnecessary overhead to me.\n> >>\n> >>>    \t}\n> >>>    \n> >>>    public:\n> >>> @@ -108,7 +107,7 @@ public:\n> >>>    \n> >>>    \tvoid invokePack(BoundMethodPackBase *pack) override\n> >>>    \t{\n> >>> -\t\tinvokePack(pack, std::make_index_sequence<sizeof...(Args)>{});\n> >>> +\t\tinvokePack(static_cast<PackType *>(pack));\n> >>\n> >> If we want to use `std::apply`, I'd inline things here:\n> > \n> > Ah good point, the private overload of invokePack() isn't needed any\n> > more. I'll send a v2.\n> > \n> >>     std::apply([&](auto&&... args /* or Args&&... args */) {\n> >>       if constexpr (!std::is_void_v<R>)\n> >>         args->ret_ = invoke(std::forward<decltype(args)>(args)...);\n> >>       else\n> >>         invoke(std::forward<decltype(args)>(args)...);\n> >>     }, std::move(args->args_));\n> > \n> > This means the pack can be used once only. It should be fine, as every\n> > bound method connected to a signal gets its own pack.\n> \n> Yes, but I believe we have recently agreed that is fine?\n> At least I have already merged https://patchwork.libcamera.org/patch/26688/\n> which does effectively the same \"move\".\n\nYes, I was just thinking out loud :-)\n\n> >>>    \t}\n> >>>    \n> >>>    \tvirtual R activate(Args... args, bool deleteMethod = false) = 0;\n> >>>\n> >>> base-commit: 2ca75f012fa12621ed70e333e635d173e92593e5","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 606B3BDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 11 May 2026 10:33:01 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 652CA6301E;\n\tMon, 11 May 2026 12:33:00 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 29FA462DC4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 11 May 2026 12:32:59 +0200 (CEST)","from killaraus.ideasonboard.com\n\t(2001-14ba-70f3-e800--a06.rev.dnainternet.fi\n\t[IPv6:2001:14ba:70f3:e800::a06])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E6F22244;\n\tMon, 11 May 2026 12:32:51 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"W5JozPUX\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1778495572;\n\tbh=1UNbU9mDzk3azCbAUhs4kH3TpbuzAodTsPIPv4jo4wo=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=W5JozPUXoE4c9KQMC6/24cJDqdrEjP3Jj+B9Drr+QWn4uiucOzCUHmDP9tZmIQYXu\n\t4A8ryP9p2GZcb5MEwdS/z+Y8bebnDMfb3ZQIFsPjXeWHMG/A/EVeHeJ6fo9htkFBOl\n\tnoJLvk9lb7IApK71WWw64DYMSKaBknmn6q398jAg=","Date":"Mon, 11 May 2026 13:32:57 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH] libcamera: bound_method: Use std::apply","Message-ID":"<20260511103257.GB2990941@killaraus.ideasonboard.com>","References":"<20260508221033.2417134-1-laurent.pinchart@ideasonboard.com>\n\t<1607e176-b22e-4ace-a9a1-b38e5f453aeb@ideasonboard.com>\n\t<20260511102038.GA2990941@killaraus.ideasonboard.com>\n\t<3479846d-5d1d-45ad-8017-ac2b6810a24f@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<3479846d-5d1d-45ad-8017-ac2b6810a24f@ideasonboard.com>","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]