diff --git a/bmrshared/include/bmrshared/function_wrapper.hpp b/bmrshared/include/bmrshared/function_wrapper.hpp index 8ee940f..9622be2 100644 --- a/bmrshared/include/bmrshared/function_wrapper.hpp +++ b/bmrshared/include/bmrshared/function_wrapper.hpp @@ -23,7 +23,8 @@ struct function_wrapper; template -requires(std::is_const::value == true) struct function_wrapper + requires(std::is_const::value == true) +struct function_wrapper { using wrapper_type = std::function; @@ -40,7 +41,8 @@ requires(std::is_const::value == true) struct function_wrapper -requires(std::is_const::value == false) struct function_wrapper + requires(std::is_const::value == false) +struct function_wrapper { using wrapper_type = std::function; diff --git a/bmrshared/include/bmrshared/invoke.hpp b/bmrshared/include/bmrshared/invoke.hpp index 9f6913f..86d4fb6 100644 --- a/bmrshared/include/bmrshared/invoke.hpp +++ b/bmrshared/include/bmrshared/invoke.hpp @@ -54,11 +54,11 @@ namespace detail template requires(function_info::is_const_member == false) - flexible_value invoke(T& callableObj, - M T::*callableFn, - std::array names, - const IDataSource& source, - TExtraArguments... arguments) +flexible_value invoke(T& callableObj, + M T::*callableFn, + std::array names, + const IDataSource& source, + TExtraArguments&&... arguments) { using CallableInfo = function_info; using SourceArgumentsTuple = @@ -74,11 +74,11 @@ requires(function_info::is_const_member == false) template requires(function_info::is_const_member == true) - flexible_value invoke(const T& callableObj, - M T::*callableFn, - std::array names, - const IDataSource& source, - TExtraArguments... arguments) +flexible_value invoke(const T& callableObj, + M T::*callableFn, + std::array names, + const IDataSource& source, + TExtraArguments&&... arguments) { using CallableInfo = function_info; using SourceArgumentsTuple = @@ -95,7 +95,7 @@ template names, const IDataSource& source, - TExtraArguments... arguments) + TExtraArguments&&... arguments) { return invoke(fn, &TCallable::operator(), names, source, arguments...); } diff --git a/bmrshared/tst/InvokeTest.cpp b/bmrshared/tst/InvokeTest.cpp index ed6c10d..62674c2 100644 --- a/bmrshared/tst/InvokeTest.cpp +++ b/bmrshared/tst/InvokeTest.cpp @@ -123,3 +123,22 @@ TEST(InvokeTest, Ok_Ptr_Member_Const) flexible_value returnValue = bmrshared::invoke(functor, &TestAddition::AddNumbersConst, names, mockSrc); EXPECT_EQ(returnValue.as(), 140); } + +TEST(InvokeTest, Ok_ExtraArgumentByRefChanged) +{ + auto fn = [](int64_t a, int64_t& lastArg) + { + lastArg = a; + return true; + }; + std::array names = {"a"}; + + MockDataSource mockSrc; + EXPECT_CALL(mockSrc, GetKeys()).WillRepeatedly(Return(std::vector{"a"})); + EXPECT_CALL(mockSrc, Get("a", An())).WillRepeatedly(SetArgReferee<1>(42)); + + int64_t lastArg = 0; + flexible_value returnValue = bmrshared::invoke(fn, names, mockSrc, lastArg); + EXPECT_EQ(returnValue.as(), true); + EXPECT_EQ(lastArg, 42); +} diff --git a/bmrshared/tst/WrapTest.cpp b/bmrshared/tst/WrapTest.cpp index fb0a79c..e58bc99 100644 --- a/bmrshared/tst/WrapTest.cpp +++ b/bmrshared/tst/WrapTest.cpp @@ -31,6 +31,17 @@ class TestAddition int64_t AddNumbersConst(int64_t left, int64_t right) const { return left + (right * 2); } }; + +class TestWriteOutputArgument +{ + public: + bool WriteOutArg(int64_t a, int64_t& extraOutArg) const + { + return extraOutArg = a; + return true; + } +}; + using TestWrapperType = function_wrapper; using TestConstWrapperType = function_wrapper; @@ -77,3 +88,20 @@ TEST(WrapTest, Const_Ptr_to_member_as_non_const) flexible_value returnValue = wrapped(obj, mockSrc); EXPECT_EQ(returnValue.as(), 84); } + +TEST(WrapTest, WriteExtraOutArg) +{ + const TestWriteOutputArgument obj; + using TestWrapperOutArgType = function_wrapper; + TestWrapperOutArgType::wrapper_type wrapped = + TestWrapperOutArgType::Wrap(&TestWriteOutputArgument::WriteOutArg, "a"); + + MockDataSource mockSrc; + EXPECT_CALL(mockSrc, GetKeys()).WillRepeatedly(Return(std::vector{"a"})); + EXPECT_CALL(mockSrc, Get("a", An())).WillRepeatedly(SetArgReferee<1>(42)); + + int64_t lastArg = 0; + flexible_value returnValue = wrapped(obj, mockSrc, lastArg); + EXPECT_EQ(returnValue.as(), true); + EXPECT_EQ(lastArg, 42); +}