From 2f8501074ea5f4c6fe650b7c29115e5b0d476bd7 Mon Sep 17 00:00:00 2001 From: Fedor Alekseev Date: Thu, 23 Oct 2025 15:10:22 +0200 Subject: [PATCH 1/2] Avoid constructing temporary T in make_box --- include/function2/function2.hpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/function2/function2.hpp b/include/function2/function2.hpp index 6453f70..d272d93 100644 --- a/include/function2/function2.hpp +++ b/include/function2/function2.hpp @@ -376,7 +376,11 @@ struct box : private Allocator { T value_; - explicit box(T value, Allocator allocator_) + explicit box(const T& value, Allocator allocator_) + : Allocator(std::move(allocator_)), value_(value) { + } + + explicit box(T&& value, Allocator allocator_) : Allocator(std::move(allocator_)), value_(std::move(value)) { } @@ -392,7 +396,11 @@ struct box : private Allocator { T value_; - explicit box(T value, Allocator allocator_) + explicit box(const T& value, Allocator allocator_) + : Allocator(std::move(allocator_)), value_(std::move(value)) { + } + + explicit box(T&& value, Allocator allocator_) : Allocator(std::move(allocator_)), value_(std::move(value)) { } From da75c3be8d5948901e72bfa0e1cd5bcf27dbc710 Mon Sep 17 00:00:00 2001 From: Fedor Alekseev Date: Thu, 23 Oct 2025 15:10:29 +0200 Subject: [PATCH 2/2] Add a regression test --- include/function2/function2.hpp | 2 +- test/regressions.cpp | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/function2/function2.hpp b/include/function2/function2.hpp index d272d93..5ab18d7 100644 --- a/include/function2/function2.hpp +++ b/include/function2/function2.hpp @@ -397,7 +397,7 @@ struct box : private Allocator { T value_; explicit box(const T& value, Allocator allocator_) - : Allocator(std::move(allocator_)), value_(std::move(value)) { + : Allocator(std::move(allocator_)), value_(value) { } explicit box(T&& value, Allocator allocator_) diff --git a/test/regressions.cpp b/test/regressions.cpp index 54ef428..63871ee 100644 --- a/test/regressions.cpp +++ b/test/regressions.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include "function2-test.hpp" @@ -261,3 +262,43 @@ TYPED_TEST(AllReferenceRetConstructTests, reference_returns_not_buildable) { ref_obj& ref = left(); ASSERT_EQ(ref.data(), 8373827); } + +/// Functor which counts the number of times it has been copied or moved +class CopyAndMoveCountFunctor { + int copy_count = 0; + int move_count = 0; + +public: + CopyAndMoveCountFunctor() = default; + + CopyAndMoveCountFunctor(const CopyAndMoveCountFunctor& that) { + *this = that; + } + + CopyAndMoveCountFunctor& operator=(const CopyAndMoveCountFunctor& that) { + copy_count = that.copy_count + 1; + move_count = that.move_count; + return *this; + } + + CopyAndMoveCountFunctor(CopyAndMoveCountFunctor&& that) { + *this = std::move(that); + } + + CopyAndMoveCountFunctor& operator=(CopyAndMoveCountFunctor&& that) { + copy_count = that.copy_count; + move_count = that.move_count + 1; + return *this; + } + + ~CopyAndMoveCountFunctor() = default; + + std::pair operator()() const { + return std::make_pair(copy_count, move_count); + } +}; + +TEST(regression_tests, no_extra_move_during_construction) { + fu2::function()> f(CopyAndMoveCountFunctor{}); + ASSERT_EQ(f(), std::make_pair(0, 2)); +}