From 2cde572532cdbc19906fafc66107840395c14cf6 Mon Sep 17 00:00:00 2001 From: Flamefire Date: Thu, 15 Nov 2018 19:47:18 +0100 Subject: [PATCH 1/2] Add -Wno-unused-local-typedefs to silence warnings breaking the build on travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b4133cc..6e027f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,7 +73,7 @@ script: - cd $PROJECT_DIR/build - export BOOST_ROOT=$BOOST # `--coverage` flags required to generate coverage info for Coveralls - - ./build.sh --toolset=$CC "cxxflags=-std=$CXX_STANDARD -Wno-unused-variable -Wno-unused-function -Wno-deprecated-declarations --coverage" "linkflags=--coverage" + - ./build.sh --toolset=$CC "cxxflags=-std=$CXX_STANDARD -Wno-unused-local-typedefs -Wno-unused-variable -Wno-unused-function -Wno-deprecated-declarations --coverage" "linkflags=--coverage" after_success: - COVERALS_DIR=$PROJECT_DIR/coverals From f402c6161e6d15dcb7c95022bb80e58cd45dbd86 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 19 Nov 2018 11:25:09 +0100 Subject: [PATCH 2/2] Fix C++98 compatibility --- doc/example/patterns_async_call.cpp | 13 +++- include/turtle/constraint.hpp | 16 +++- include/turtle/constraints.hpp | 5 +- include/turtle/detail/action.hpp | 11 ++- .../turtle/detail/expectation_template.hpp | 18 ++--- include/turtle/detail/function.hpp | 1 + .../turtle/detail/function_impl_template.hpp | 8 +- include/turtle/detail/function_template.hpp | 8 +- .../turtle/detail/matcher_base_template.hpp | 8 +- include/turtle/detail/move_helper.hpp | 78 +++++++++++++++++++ include/turtle/matcher.hpp | 12 +-- include/turtle/mock.hpp | 2 +- test/test_constraints.cpp | 3 +- 13 files changed, 146 insertions(+), 37 deletions(-) create mode 100644 include/turtle/detail/move_helper.hpp diff --git a/doc/example/patterns_async_call.cpp b/doc/example/patterns_async_call.cpp index 888be3e..e1b2a60 100644 --- a/doc/example/patterns_async_call.cpp +++ b/doc/example/patterns_async_call.cpp @@ -49,6 +49,10 @@ namespace { MOCK_METHOD( method, 0 ) }; + void set_bool(bool& b) + { + b = true; + } } BOOST_AUTO_TEST_CASE( method_is_called ) @@ -56,7 +60,14 @@ BOOST_AUTO_TEST_CASE( method_is_called ) mock_base_class m; my_class c( m ); bool done = false; - MOCK_EXPECT( m.method ).once().calls( boost::lambda::var( done ) = true ); // when method is called it will set done to true + // when method is called it will set done to true + // Note: Boost 1.57 introduced a bug preventing usage of the lambda with clang in C++98 + // See: https://svn.boost.org/trac10/ticket/10785 +#if defined(BOOST_CLANG) && (BOOST_VERSION >= 105700) + MOCK_EXPECT( m.method ).once().calls( boost::bind(&set_bool, done) ); +#else + MOCK_EXPECT( m.method ).once().calls( boost::lambda::var( done ) = true ); +#endif check( done, boost::bind( &my_class::flush, &c ) ); // just wait on done, flushing from time to time } //] diff --git a/include/turtle/constraint.hpp b/include/turtle/constraint.hpp index 081c04d..25aa160 100644 --- a/include/turtle/constraint.hpp +++ b/include/turtle/constraint.hpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace mock { @@ -146,7 +147,7 @@ namespace detail const mock::constraint< detail::Name > Name; #define MOCK_CONSTRAINT_ASSIGN(z, n, d) \ - expected##n( e##n ) + expected##n( boost::forward< T##n >(e##n) ) #define MOCK_CONSTRAINT_UNWRAP_REF(z, n, d) \ boost::unwrap_ref( expected##n ) @@ -157,6 +158,9 @@ namespace detail #define MOCK_CONSTRAINT_MEMBER(z, n, d) \ Expected_##n expected##n; +#define MOCK_CONSTRAINT_TPL_TYPE(z, n, d) \ + typename boost::decay< const T##n >::type + #define MOCK_CONSTRAINT_CREF_PARAM(z, n, Args) \ const typename boost::unwrap_reference< Expected_##n >::type& \ BOOST_PP_ARRAY_ELEM(n, Args) @@ -164,6 +168,9 @@ namespace detail #define MOCK_CONSTRAINT_ARG(z, n, Args) \ BOOST_FWD_REF(T##n) BOOST_PP_ARRAY_ELEM(n, Args) +#define MOCK_CONSTRAINT_ARGS(z, n, Args) \ + BOOST_FWD_REF(T##n) e##n + #define MOCK_CONSTRAINT_PARAM(z, n, Args) \ boost::forward< T##n >( BOOST_PP_ARRAY_ELEM(n, Args) ) @@ -173,8 +180,9 @@ namespace detail template< BOOST_PP_ENUM_PARAMS(n, typename Expected_) > \ struct Name \ { \ + template< BOOST_PP_ENUM_PARAMS(n, typename T) > \ explicit Name( \ - BOOST_PP_ENUM_BINARY_PARAMS(n, Expected_, e) ) \ + BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ARGS, _) ) \ : BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ASSIGN, _) \ {} \ template< typename Actual > \ @@ -201,10 +209,10 @@ namespace detail } \ template< BOOST_PP_ENUM_PARAMS(n, typename T) > \ mock::constraint< \ - detail::Name< BOOST_PP_ENUM_PARAMS(n, T) > \ + detail::Name< BOOST_PP_ENUM(n, MOCK_CONSTRAINT_TPL_TYPE, _) > \ > Name( BOOST_PP_ENUM(n, MOCK_CONSTRAINT_ARG, (n, Args)) ) \ { \ - return detail::Name< BOOST_PP_ENUM_PARAMS(n, T) >( \ + return detail::Name< BOOST_PP_ENUM(n, MOCK_CONSTRAINT_TPL_TYPE, _) >( \ BOOST_PP_ENUM(n, MOCK_CONSTRAINT_PARAM, (n, Args)) ); \ } diff --git a/include/turtle/constraints.hpp b/include/turtle/constraints.hpp index 5433874..52931b8 100644 --- a/include/turtle/constraints.hpp +++ b/include/turtle/constraints.hpp @@ -12,6 +12,7 @@ #include "config.hpp" #include "constraint.hpp" #include "detail/addressof.hpp" +#include "detail/move_helper.hpp" #include #include #include @@ -269,9 +270,9 @@ namespace detail } template< typename T > - constraint< detail::equal< T > > equal( BOOST_FWD_REF(T) t ) + constraint< detail::equal< typename detail::forward_type< T >::type > > equal( BOOST_FWD_REF(T) t ) { - return detail::equal< T >( boost::forward< T >( t ) ); + return detail::equal< typename detail::forward_type< T >::type >( boost::forward< T >( t ) ); } template< typename T > diff --git a/include/turtle/detail/action.hpp b/include/turtle/detail/action.hpp index ed055d2..a146130 100644 --- a/include/turtle/detail/action.hpp +++ b/include/turtle/detail/action.hpp @@ -109,17 +109,16 @@ namespace detail { this->set( boost::bind( - &move< Value >, + &move< typename boost::remove_reference< Value >::type >, boost::ref( store( boost::move( v ) ) ) ) ); } private: - template< typename T > - static T&& move( T& t ) + template< typename Value > + static BOOST_RV_REF(Value) move( Value& t ) { - return std::move( t ); + return boost::move( t ); } - struct value : boost::noncopyable { virtual ~value() @@ -138,7 +137,7 @@ namespace detail value_imp( BOOST_RV_REF(value_type) t ) : t_( boost::move( t ) ) {} - value_imp( const T& t ) + value_imp( const value_type& t ) : t_( t ) {} template< typename Y > diff --git a/include/turtle/detail/expectation_template.hpp b/include/turtle/detail/expectation_template.hpp index 33d6487..030a062 100644 --- a/include/turtle/detail/expectation_template.hpp +++ b/include/turtle/detail/expectation_template.hpp @@ -15,7 +15,7 @@ matcher< T##n, Constraint_##n > c##n##_; #define MOCK_EXPECTATION_IS_VALID(z, n, d) \ - BOOST_PP_IF(n, &&,) c##n##_( boost::forward< T##n >( a##n ) ) + BOOST_PP_IF(n, &&,) c##n##_( mock::detail::move_if_not_lvalue_reference< T##n >( a##n ) ) #define MOCK_EXPECTATION_SERIALIZE(z, n, d) \ BOOST_PP_IF(n, << ", " <<,) c##n##_ @@ -24,10 +24,10 @@ BOOST_PP_IF(n, << ", " <<,) "any" #define MOCK_EXPECTATION_PARAM(z, n, Args) \ - boost::forward< T##n >( a##n ) + mock::detail::move_if_not_lvalue_reference< T##n >( a##n ) -#define MOCK_RV_REF_ARG(z, n, d) \ - BOOST_RV_REF(T##n) a##n +#define MOCK_REF_ARG(z, n, d) \ + typename ref_arg< T##n >::type a##n namespace mock { @@ -42,7 +42,7 @@ namespace detail { private: virtual bool operator()( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_RV_REF, _) ) + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG, _) ) { return true; } @@ -76,7 +76,7 @@ namespace detail private: virtual bool operator()( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_RV_REF_ARG, _) ) + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG, _) ) { return BOOST_PP_REPEAT(MOCK_NUM_ARGS, MOCK_EXPECTATION_IS_VALID, _); @@ -106,7 +106,7 @@ namespace detail private: virtual bool operator()( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_RV_REF_ARG, _) ) + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG, _) ) { return f_( BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_EXPECTATION_PARAM, _) ); } @@ -204,7 +204,7 @@ namespace detail } bool is_valid( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_RV_REF_ARG, _) ) const + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG, _) ) const { return !invocation_->exhausted() && (*matcher_)( BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_EXPECTATION_PARAM, _) ); @@ -268,5 +268,5 @@ namespace detail #undef MOCK_EXPECTATION_SERIALIZE #undef MOCK_EXPECTATION_SERIALIZE_ANY #undef MOCK_EXPECTATION_PARAM -#undef MOCK_RV_REF_ARG +#undef MOCK_REF_ARG #undef MOCK_RV_REF diff --git a/include/turtle/detail/function.hpp b/include/turtle/detail/function.hpp index 7432384..a17dfec 100644 --- a/include/turtle/detail/function.hpp +++ b/include/turtle/detail/function.hpp @@ -21,6 +21,7 @@ #include "type_name.hpp" #include "context.hpp" #include "mutex.hpp" +#include "move_helper.hpp" #include #include #include diff --git a/include/turtle/detail/function_impl_template.hpp b/include/turtle/detail/function_impl_template.hpp index 4d47a82..5a29b3b 100644 --- a/include/turtle/detail/function_impl_template.hpp +++ b/include/turtle/detail/function_impl_template.hpp @@ -24,6 +24,9 @@ << ')' \ << lazy_expectations( this ) +#define MOCK_MOVE(z, n, d) \ + mock::detail::move_if_not_lvalue_reference< T##n >( t##n ) + namespace mock { namespace detail @@ -217,7 +220,7 @@ namespace detail for( expectations_cit it = expectations_.begin(); it != expectations_.end(); ++it ) if( it->is_valid( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _) ) ) + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_MOVE, _) ) ) { if( ! it->invoke() ) { @@ -236,7 +239,7 @@ namespace detail MOCK_FUNCTION_CONTEXT, it->file(), it->line() ); if( it->functor() ) return it->functor()( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _) ); + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_MOVE, _) ); return it->trigger(); } error_type::fail( "unexpected call", MOCK_FUNCTION_CONTEXT ); @@ -309,3 +312,4 @@ namespace detail #undef MOCK_FUNCTION_FORMAT #undef MOCK_FUNCTION_CONTEXT +#undef MOCK_MOVE diff --git a/include/turtle/detail/function_template.hpp b/include/turtle/detail/function_template.hpp index 04a0ad2..0ebfe14 100644 --- a/include/turtle/detail/function_template.hpp +++ b/include/turtle/detail/function_template.hpp @@ -8,8 +8,8 @@ #include "function_impl_template.hpp" -#define MOCK_FORWARD(z, n, d) \ - boost::forward< T##n >( t##n ) +#define MOCK_MOVE(z, n, d) \ + mock::detail::move_if_not_lvalue_reference< T##n >( t##n ) namespace mock { @@ -74,7 +74,7 @@ namespace detail R operator()( BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, t) ) const { - return (*impl_)( BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_FORWARD, _) ); + return (*impl_)( BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_MOVE, _) ); } friend std::ostream& operator<<( std::ostream& s, const function& f ) @@ -102,3 +102,5 @@ namespace detail }; } } // mock + +#undef MOCK_MOVE diff --git a/include/turtle/detail/matcher_base_template.hpp b/include/turtle/detail/matcher_base_template.hpp index f8b64ee..07fa326 100644 --- a/include/turtle/detail/matcher_base_template.hpp +++ b/include/turtle/detail/matcher_base_template.hpp @@ -6,8 +6,8 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#define MOCK_RV_REF(z, n, d) \ - BOOST_RV_REF(T##n) +#define MOCK_REF_ARG(z, n, d) \ + typename ref_arg< T##n >::type namespace mock { @@ -24,7 +24,7 @@ namespace detail virtual ~matcher_base() {} virtual bool operator()( - BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_RV_REF, _) ) = 0; + BOOST_PP_ENUM(MOCK_NUM_ARGS, MOCK_REF_ARG, _) ) = 0; friend std::ostream& operator<<( std::ostream& s, const matcher_base& m ) @@ -38,3 +38,5 @@ namespace detail }; } } // mock + +#undef MOCK_REF_ARG diff --git a/include/turtle/detail/move_helper.hpp b/include/turtle/detail/move_helper.hpp new file mode 100644 index 0000000..87f1f2d --- /dev/null +++ b/include/turtle/detail/move_helper.hpp @@ -0,0 +1,78 @@ +// http://turtle.sourceforge.net +// +// Copyright Mathieu Champlon 2018 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef MOCK_MOVE_HELPER_HPP_INCLUDED +#define MOCK_MOVE_HELPER_HPP_INCLUDED + +#include "../config.hpp" +#include +#include +#include +#include +#include +#include + +namespace mock +{ +namespace detail +{ +#ifdef MOCK_RVALUE_REFERENCES + template< typename T > + struct forward_type + { + typedef T type; + }; + template< typename T > + struct ref_arg + { + typedef typename boost::conditional< + boost::is_reference< T >::value, + T, + typename boost::add_rvalue_reference< T >::type >::type type; + }; + + template< typename T > + inline T&& move_if_not_lvalue_reference(typename boost::remove_reference< T >::type& t) + { + return static_cast< T&& >(t); + } + + template< typename T > + inline T&& move_if_not_lvalue_reference(typename boost::remove_reference< T >::type&& t) + { + return static_cast< T&& >(t); + } +#else + template< typename T > + struct forward_type + { + typedef typename boost::decay< const T >::type type; + }; + template< class T> + struct forward_type< boost::rv< T > > + { + typedef T type; + }; + template< typename T > + struct ref_arg + { + typedef typename boost::conditional< + boost::is_reference< T >::value, + T, + const typename boost::add_reference< T >::type >::type type; + }; + template< typename T > + inline typename boost::remove_reference< T >::type& move_if_not_lvalue_reference(typename boost::remove_reference< T >::type& t) + { + return t; + } +#endif +} +} + +#endif // MOCK_MOVE_HELPER_HPP_INCLUDED diff --git a/include/turtle/matcher.hpp b/include/turtle/matcher.hpp index 91f1f23..c6082a7 100644 --- a/include/turtle/matcher.hpp +++ b/include/turtle/matcher.hpp @@ -13,7 +13,9 @@ #include "log.hpp" #include "constraints.hpp" #include "detail/is_functor.hpp" +#include "detail/move_helper.hpp" #include +#include #include #include @@ -26,7 +28,7 @@ namespace mock explicit matcher( Expected expected ) : expected_( expected ) {} - bool operator()( const Actual& actual ) + bool operator()( typename boost::add_reference< const Actual >::type actual ) { return mock::equal( boost::unwrap_ref( expected_ ) ).c_( actual ); @@ -67,9 +69,9 @@ namespace mock explicit matcher( const constraint< Constraint >& c ) : c_( c.c_ ) {} - bool operator()( BOOST_RV_REF(Actual) actual ) + bool operator()( typename detail::ref_arg< Actual >::type actual ) { - return c_( boost::forward< Actual >( actual ) ); + return c_( mock::detail::move_if_not_lvalue_reference< typename detail::ref_arg< Actual >::type >( actual ) ); } friend std::ostream& operator<<( std::ostream& s, const matcher& m ) @@ -91,9 +93,9 @@ namespace mock explicit matcher( const Functor& f ) : c_( f ) {} - bool operator()( BOOST_RV_REF(Actual) actual ) + bool operator()( typename detail::ref_arg< Actual >::type actual ) { - return c_( boost::forward< Actual >( actual ) ); + return c_( mock::detail::move_if_not_lvalue_reference< typename detail::ref_arg< Actual >::type >( actual ) ); } friend std::ostream& operator<<( std::ostream& s, const matcher& m ) diff --git a/include/turtle/mock.hpp b/include/turtle/mock.hpp index 204061d..a5f1f1c 100644 --- a/include/turtle/mock.hpp +++ b/include/turtle/mock.hpp @@ -87,7 +87,7 @@ BOOST_PP_COMMA_IF(n) d, n >::type >( p##n ) #define MOCK_FORWARD_PARAMS(n, S, tpn) \ BOOST_PP_REPEAT(n, MOCK_FORWARD_PARAM, \ - boost::forward< MOCK_PARAM(S, tpn)) + mock::detail::move_if_not_lvalue_reference< MOCK_PARAM(S, tpn)) #define MOCK_METHOD_AUX(M, n, S, t, c, tpn) \ MOCK_DECL(M, n, S, c, tpn) \ { \ diff --git a/test/test_constraints.cpp b/test/test_constraints.cpp index 27d1782..9e918da 100644 --- a/test/test_constraints.cpp +++ b/test/test_constraints.cpp @@ -8,6 +8,7 @@ #include #include +#include BOOST_AUTO_TEST_CASE( all_comparison_constraints_can_be_instanciated ) { @@ -47,7 +48,7 @@ BOOST_AUTO_TEST_CASE( equal_constraint ) BOOST_CHECK( ! mock::equal( std::string( "string" ) ).c_( "not string" ) ); { std::string s; - auto c = mock::equal( boost::cref( s ) ); + BOOST_AUTO( c, mock::equal( boost::cref( s ) ) ); s = "string"; BOOST_CHECK( c.c_( "string" ) ); }