mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
Workaround compiler issues (constant conditions, compiler bugs...)
MSVC has issues with a tuple of references of incomplete classes and `virtual ~value() = default;` Some compilers warn for constant expressions in the for-loop-condition
This commit is contained in:
parent
fca30e7780
commit
baaaa15489
3 changed files with 70 additions and 48 deletions
|
|
@ -62,6 +62,27 @@ namespace mock { namespace detail {
|
|||
action_type a_;
|
||||
};
|
||||
|
||||
/// Type erased value storage
|
||||
struct value
|
||||
{
|
||||
value() = default;
|
||||
value(const value&) = delete;
|
||||
value& operator=(const value&) = delete;
|
||||
virtual ~value() = default;
|
||||
};
|
||||
/// Actual value storage,
|
||||
/// holds an instance of T (stripped of reference qualifiers)
|
||||
template<typename T>
|
||||
struct value_imp : value
|
||||
{
|
||||
using type = std::remove_const_t<std::remove_reference_t<T>>;
|
||||
|
||||
template<typename U>
|
||||
value_imp(U&& t) : t_(std::forward<U>(t))
|
||||
{}
|
||||
type t_;
|
||||
};
|
||||
|
||||
template<typename Result, typename Signature>
|
||||
class action : public action_base<Result, Signature>
|
||||
{
|
||||
|
|
@ -85,24 +106,6 @@ namespace mock { namespace detail {
|
|||
}
|
||||
|
||||
private:
|
||||
struct value
|
||||
{
|
||||
value() = default;
|
||||
value(const value&) = delete;
|
||||
value& operator=(const value&) = delete;
|
||||
virtual ~value() = default;
|
||||
};
|
||||
template<typename T>
|
||||
struct value_imp : value
|
||||
{
|
||||
typedef std::remove_const_t<std::remove_reference_t<T>> type;
|
||||
|
||||
template<typename U>
|
||||
value_imp(U&& t) : t_(std::forward<U>(t))
|
||||
{}
|
||||
type t_;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
typename value_imp<T>::type& store(T&& t)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ namespace mock { namespace detail {
|
|||
bool operator()(typename ref_arg<Args>::type...) override { return true; }
|
||||
void serialize(std::ostream& s) const override
|
||||
{
|
||||
for(unsigned i = 0; i < sizeof...(Args); ++i)
|
||||
constexpr auto arity = sizeof...(Args);
|
||||
for(unsigned i = 0; i < arity; ++i)
|
||||
{
|
||||
if(i)
|
||||
s << ", ";
|
||||
|
|
@ -99,7 +100,7 @@ namespace mock { namespace detail {
|
|||
template<typename R, typename... Args>
|
||||
class expectation<R(Args...)> : public action<R, R(Args...)>
|
||||
{
|
||||
static constexpr auto arity = sizeof...(Args);
|
||||
static constexpr std::size_t arity = sizeof...(Args);
|
||||
|
||||
public:
|
||||
expectation() : expectation("unknown location", 0) {}
|
||||
|
|
@ -122,13 +123,13 @@ namespace mock { namespace detail {
|
|||
void invoke(std::unique_ptr<invocation> i) { invocation_ = std::move(i); }
|
||||
|
||||
template<typename... Constraints>
|
||||
std::enable_if_t<(arity > 0) && sizeof...(Constraints) == arity, expectation&> with(Constraints... c)
|
||||
std::enable_if_t<(arity > 0u) && sizeof...(Constraints) == arity, expectation&> with(Constraints... c)
|
||||
{
|
||||
matcher_ = std::make_unique<single_matcher<void(Constraints...), Args...>>(c...);
|
||||
return *this;
|
||||
}
|
||||
template<typename Constraint, std::size_t Arity = arity>
|
||||
std::enable_if_t<(Arity > 1), expectation&> with(const Constraint& c)
|
||||
std::enable_if_t<(Arity > 1u), expectation&> with(const Constraint& c)
|
||||
{
|
||||
matcher_ = std::make_unique<multi_matcher<Constraint, Args...>>(c);
|
||||
return *this;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ namespace mock { namespace detail {
|
|||
#endif
|
||||
}
|
||||
|
||||
template<typename... Arg>
|
||||
class lazy_args;
|
||||
|
||||
template<typename Signature>
|
||||
class function_impl;
|
||||
|
||||
|
|
@ -133,7 +136,7 @@ namespace mock { namespace detail {
|
|||
{
|
||||
private:
|
||||
typedef wrapper_base<R, expectation_type> base_type;
|
||||
static constexpr auto arity = sizeof...(Args);
|
||||
static constexpr std::size_t arity = sizeof...(Args);
|
||||
|
||||
public:
|
||||
wrapper(const std::shared_ptr<mutex>& m, expectation_type& e) : base_type(e), lock_(m) {}
|
||||
|
|
@ -238,8 +241,9 @@ namespace mock { namespace detail {
|
|||
R operator()(Args... args) const
|
||||
{
|
||||
// Due to lifetime rules of references this must be created and consumed in one line
|
||||
#define MOCK_FUNCTION_CONTEXT \
|
||||
boost::unit_test::lazy_ostream::instance() << lazy_context(this) << lazy_args(args...) << lazy_expectations(this)
|
||||
#define MOCK_FUNCTION_CONTEXT \
|
||||
boost::unit_test::lazy_ostream::instance() \
|
||||
<< lazy_context(this) << lazy_args<Args...>(args...) << lazy_expectations(this)
|
||||
|
||||
lock _(mutex_);
|
||||
valid_ = false;
|
||||
|
|
@ -316,35 +320,49 @@ namespace mock { namespace detail {
|
|||
const function_impl* impl_;
|
||||
};
|
||||
|
||||
struct lazy_args
|
||||
{
|
||||
lazy_args(std::add_lvalue_reference_t<Args>... args) : args_(args...) {}
|
||||
friend std::ostream& operator<<(std::ostream& s, const lazy_args& a)
|
||||
{
|
||||
return a.print_impl(std::make_index_sequence<sizeof...(Args)>{}, s);
|
||||
}
|
||||
|
||||
private:
|
||||
std::tuple<std::add_lvalue_reference_t<Args>...> args_;
|
||||
|
||||
template<std::size_t... I>
|
||||
std::ostream& print_impl(std::index_sequence<I...>, std::ostream& s) const
|
||||
{
|
||||
s << '(';
|
||||
using expander = int[];
|
||||
(void)expander{
|
||||
0, (s << ' ' << mock::format(std::get<I>(args_)) << (sizeof...(Args) - 1u == I ? ' ' : ','), 0)...
|
||||
};
|
||||
return s << ')';
|
||||
}
|
||||
};
|
||||
|
||||
std::list<expectation_type> expectations_;
|
||||
context* context_;
|
||||
mutable bool valid_;
|
||||
const int exceptions_;
|
||||
const std::shared_ptr<mutex> mutex_;
|
||||
};
|
||||
|
||||
template<typename ArgFirst, typename... ArgRest>
|
||||
class lazy_args<ArgFirst, ArgRest...> : lazy_args<ArgRest...>
|
||||
{
|
||||
ArgFirst& arg_;
|
||||
|
||||
public:
|
||||
lazy_args(ArgFirst& arg, std::add_lvalue_reference_t<ArgRest>... args)
|
||||
: lazy_args<ArgRest...>(args...), arg_(arg)
|
||||
{}
|
||||
std::ostream& print(std::ostream& s) const
|
||||
{
|
||||
s << ' ' << mock::format(arg_) << ',';
|
||||
return lazy_args<ArgRest...>::print(s);
|
||||
}
|
||||
};
|
||||
template<typename ArgFirst>
|
||||
class lazy_args<ArgFirst>
|
||||
{
|
||||
ArgFirst& arg_;
|
||||
|
||||
public:
|
||||
lazy_args(ArgFirst& arg) : arg_(arg) {}
|
||||
std::ostream& print(std::ostream& s) const { return s << ' ' << mock::format(arg_) << ' '; }
|
||||
};
|
||||
template<>
|
||||
class lazy_args<>
|
||||
{
|
||||
public:
|
||||
std::ostream& print(std::ostream& s) const { return s; }
|
||||
};
|
||||
template<typename... Args>
|
||||
std::ostream& operator<<(std::ostream& s, const lazy_args<Args...>& a)
|
||||
{
|
||||
s << '(';
|
||||
return a.print(s) << ')';
|
||||
}
|
||||
}} // namespace mock::detail
|
||||
|
||||
#endif // MOCK_FUNCTION_IMPL_HPP_INCLUDED
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue