Skip to content

Commit

Permalink
Changed ReturnCopy to ReturnCapture that can also capture by move + r…
Browse files Browse the repository at this point in the history
…eplaced implicit ReturnCopy by compile error.
  • Loading branch information
FranckRJ committed Apr 21, 2024
1 parent 5fc5592 commit 6ecefba
Show file tree
Hide file tree
Showing 2 changed files with 282 additions and 147 deletions.
100 changes: 51 additions & 49 deletions include/fakeit/StubbingProgress.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ namespace fakeit {
return DoImpl(new Repeat<R, arglist...>(method));
}

virtual void AlwaysDo(std::function<R(const typename fakeit::test_arg<arglist>::type...)> method) {
DoImpl(new RepeatForever<R, arglist...>(method));
}

protected:
virtual MethodStubbingProgress<R, arglist...>& DoImpl(Action<R, arglist...> *action) = 0;
};
Expand All @@ -61,16 +65,57 @@ namespace fakeit {
template<typename R, typename ... arglist>
struct BasicReturnImpl<R, true, arglist...> : public BasicDoImpl<R, arglist...> {
using BasicDoImpl<R, arglist...>::Do;
using BasicDoImpl<R, arglist...>::AlwaysDo;

MethodStubbingProgress<R, arglist...>& Return(const R& r) {
return Do([&r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; });
}

template <typename U = R>
MethodStubbingProgress<R, arglist...>& Return(typename std::remove_cv<typename std::remove_reference<R>::type>::type&& r) {
static_assert(sizeof(U) != sizeof(U), "Return() cannot take an rvalue references for functions returning a reference because it would make it dangling, use ReturnCapture() instead.");
return Return(r); // Only written to silence warning about not returning from a non-void function, but will never be executed.
}

void AlwaysReturn(const R &r) {
return AlwaysDo([&r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; });
}

template <typename U = R>
void AlwaysReturn(typename std::remove_cv<typename std::remove_reference<R>::type>::type&&) {
static_assert(sizeof(U) != sizeof(U), "AlwaysReturn() cannot take an rvalue references for functions returning a reference because it would make it dangling, use AlwaysReturnCapture() instead.");
}

template<typename T>
MethodStubbingProgress<R, arglist...>& ReturnCapture(T&& r) {
static_assert(std::is_constructible<
typename std::remove_cv<typename std::remove_reference<R>::type>::type&,
typename std::remove_cv<typename std::remove_reference<T>::type>::type&>::value,
"The type captured by ReturnCapture() (named T) must be compatible with the return type of the function (named R), i.e. T t{...}; R& r = t; must compile without creating temporaries.");
auto store = std::make_shared<typename std::remove_cv<typename std::remove_reference<T>::type>::type>(std::forward<T>(r));
return Do([store](const typename fakeit::test_arg<arglist>::type...) mutable -> R {
return std::forward<R>(*store);
});
}

template<typename T>
void AlwaysReturnCapture(T&& r) {
static_assert(std::is_constructible<
typename std::remove_cv<typename std::remove_reference<R>::type>::type&,
typename std::remove_cv<typename std::remove_reference<T>::type>::type&>::value,
"The type captured by AlwaysReturnCapture() (named T) must be compatible with the return type of the function (named R), i.e. T t{...}; R& r = t; must compile without creating temporaries.");
auto store = std::make_shared<typename std::remove_cv<typename std::remove_reference<T>::type>::type>(std::forward<T>(r));
return AlwaysDo([store](const typename fakeit::test_arg<arglist>::type...) mutable -> R {
return std::forward<R>(*store);
});
}
};

// If R is not a reference.
template<typename R, typename ... arglist>
struct BasicReturnImpl<R, false, arglist...> : public BasicDoImpl<R, arglist...> {
using BasicDoImpl<R, arglist...>::Do;
using BasicDoImpl<R, arglist...>::AlwaysDo;

MethodStubbingProgress<R, arglist...>& Return(const R& r) {
return Do([r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; });
Expand All @@ -82,6 +127,10 @@ namespace fakeit {
return std::move(*store);
});
}

void AlwaysReturn(const R &r) {
return AlwaysDo([r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; });
}
};

template<typename R, typename ... arglist>
Expand All @@ -97,23 +146,9 @@ namespace fakeit {

public:
using helper::BasicReturnImplHelper<R, arglist...>::Do;
using helper::BasicReturnImplHelper<R, arglist...>::AlwaysDo;
using helper::BasicReturnImplHelper<R, arglist...>::Return;

template<typename T>
typename std::enable_if<!std::is_reference<T>::value && std::is_copy_constructible<T>::value, MethodStubbingProgress<R, arglist...>&>::type
Return(T&& t) {
auto store = std::make_shared<T>(std::move(t));
return Do([store](const typename fakeit::test_arg<arglist>::type...) mutable->R
{
return *store;
});
}

template<typename U = R>
typename std::enable_if<std::is_copy_constructible<U>::value, MethodStubbingProgress<R, arglist...>&>::type
ReturnCopy(const R& r) {
return Do([r](const typename fakeit::test_arg<arglist>::type...) mutable -> R { return r; });
}
using helper::BasicReturnImplHelper<R, arglist...>::AlwaysReturn;

MethodStubbingProgress<R, arglist...> &
Return(const Quantifier<R> &q) {
Expand All @@ -129,35 +164,6 @@ namespace fakeit {
return Return(std::forward<Second>(s), std::forward<Tail>(t)...);
}


template<typename U = R>
typename std::enable_if<!std::is_reference<U>::value, void>::type
AlwaysReturn(const R &r) {
return AlwaysDo([r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; });
}

template<typename T>
typename std::enable_if<!std::is_reference<T>::value && std::is_copy_constructible<T>::value, void>::type
AlwaysReturn(T&& t) {
auto store = std::make_shared<T>(std::move(t));
return AlwaysDo([store](const typename fakeit::test_arg<arglist>::type...) mutable -> R
{
return *store;
});
}

template<typename U = R>
typename std::enable_if<std::is_reference<U>::value, void>::type
AlwaysReturn(const R &r) {
return AlwaysDo([&r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; });
}

template<typename U = R>
typename std::enable_if<std::is_copy_constructible<U>::value, void>::type
AlwaysReturnCopy(const R& r) {
return AlwaysDo([r](const typename fakeit::test_arg<arglist>::type...) mutable -> R { return r; });
}

MethodStubbingProgress<R, arglist...> &
Return() {
return Do([](const typename fakeit::test_arg<arglist>::type...) -> R { return DefaultValue<R>::value(); });
Expand Down Expand Up @@ -218,10 +224,6 @@ namespace fakeit {
return Do(s, t...);
}

virtual void AlwaysDo(std::function<R(const typename fakeit::test_arg<arglist>::type...)> method) {
DoImpl(new RepeatForever<R, arglist...>(method));
}

private:
MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete;

Expand Down
Loading

0 comments on commit 6ecefba

Please sign in to comment.