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_;
|
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>
|
template<typename Result, typename Signature>
|
||||||
class action : public action_base<Result, Signature>
|
class action : public action_base<Result, Signature>
|
||||||
{
|
{
|
||||||
|
|
@ -85,24 +106,6 @@ namespace mock { namespace detail {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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>
|
template<typename T>
|
||||||
typename value_imp<T>::type& store(T&& 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; }
|
bool operator()(typename ref_arg<Args>::type...) override { return true; }
|
||||||
void serialize(std::ostream& s) const override
|
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)
|
if(i)
|
||||||
s << ", ";
|
s << ", ";
|
||||||
|
|
@ -99,7 +100,7 @@ namespace mock { namespace detail {
|
||||||
template<typename R, typename... Args>
|
template<typename R, typename... Args>
|
||||||
class expectation<R(Args...)> : public action<R, R(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:
|
public:
|
||||||
expectation() : expectation("unknown location", 0) {}
|
expectation() : expectation("unknown location", 0) {}
|
||||||
|
|
@ -122,13 +123,13 @@ namespace mock { namespace detail {
|
||||||
void invoke(std::unique_ptr<invocation> i) { invocation_ = std::move(i); }
|
void invoke(std::unique_ptr<invocation> i) { invocation_ = std::move(i); }
|
||||||
|
|
||||||
template<typename... Constraints>
|
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...);
|
matcher_ = std::make_unique<single_matcher<void(Constraints...), Args...>>(c...);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<typename Constraint, std::size_t Arity = arity>
|
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);
|
matcher_ = std::make_unique<multi_matcher<Constraint, Args...>>(c);
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,9 @@ namespace mock { namespace detail {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename... Arg>
|
||||||
|
class lazy_args;
|
||||||
|
|
||||||
template<typename Signature>
|
template<typename Signature>
|
||||||
class function_impl;
|
class function_impl;
|
||||||
|
|
||||||
|
|
@ -133,7 +136,7 @@ namespace mock { namespace detail {
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
typedef wrapper_base<R, expectation_type> base_type;
|
typedef wrapper_base<R, expectation_type> base_type;
|
||||||
static constexpr auto arity = sizeof...(Args);
|
static constexpr std::size_t arity = sizeof...(Args);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wrapper(const std::shared_ptr<mutex>& m, expectation_type& e) : base_type(e), lock_(m) {}
|
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
|
R operator()(Args... args) const
|
||||||
{
|
{
|
||||||
// Due to lifetime rules of references this must be created and consumed in one line
|
// Due to lifetime rules of references this must be created and consumed in one line
|
||||||
#define MOCK_FUNCTION_CONTEXT \
|
#define MOCK_FUNCTION_CONTEXT \
|
||||||
boost::unit_test::lazy_ostream::instance() << lazy_context(this) << lazy_args(args...) << lazy_expectations(this)
|
boost::unit_test::lazy_ostream::instance() \
|
||||||
|
<< lazy_context(this) << lazy_args<Args...>(args...) << lazy_expectations(this)
|
||||||
|
|
||||||
lock _(mutex_);
|
lock _(mutex_);
|
||||||
valid_ = false;
|
valid_ = false;
|
||||||
|
|
@ -316,35 +320,49 @@ namespace mock { namespace detail {
|
||||||
const function_impl* impl_;
|
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_;
|
std::list<expectation_type> expectations_;
|
||||||
context* context_;
|
context* context_;
|
||||||
mutable bool valid_;
|
mutable bool valid_;
|
||||||
const int exceptions_;
|
const int exceptions_;
|
||||||
const std::shared_ptr<mutex> mutex_;
|
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
|
}} // namespace mock::detail
|
||||||
|
|
||||||
#endif // MOCK_FUNCTION_IMPL_HPP_INCLUDED
|
#endif // MOCK_FUNCTION_IMPL_HPP_INCLUDED
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue