Added support for C++11 lambdas as constraints

git-svn-id: https://svn.code.sf.net/p/turtle/code/trunk@620 860be788-9bd5-4423-9f1e-828f051e677b
This commit is contained in:
mat007 2013-04-11 16:24:26 +00:00
parent c5861a744d
commit 4afe1d32d4
6 changed files with 77 additions and 10 deletions

View file

@ -261,4 +261,10 @@ This is actually a bug in the compiler, for more information see [@http://connec
[endsect] [endsect]
[section Using C++11 lambda as constraints requires decltype compiler support]
The technique used in order to detect whether a constraint is a C++11 lambda or not is based on decltype, which means the library can fail to detect a lambda in case the compiler does not support it.
[endsect]
[endsect] [endsect]

View file

@ -590,6 +590,14 @@ Example using [@http://www.boost.org/libs/phoenix Boost.Phoenix] :
MOCK_EXPECT( c.method ).with( boost::phoenix::arg_names::_1 == 42 ); MOCK_EXPECT( c.method ).with( boost::phoenix::arg_names::_1 == 42 );
} }
Example using C++11 lambdas :
BOOST_AUTO_TEST_CASE( demonstrates_adding_a_constraint_with_cxx11_lambda )
{
mock_class c;
MOCK_EXPECT( c.method ).with( []( int actual ) { return 42 == actual; } );
}
Example using &&, || and ! : Example using &&, || and ! :
BOOST_AUTO_TEST_CASE( demonstrates_combining_constraints ) BOOST_AUTO_TEST_CASE( demonstrates_combining_constraints )

View file

@ -22,12 +22,17 @@
namespace namespace
{ {
struct declared_but_not_defined; struct declared_but_not_defined;
BOOST_MPL_ASSERT_NOT(( mock::detail::is_functor< declared_but_not_defined > )); BOOST_MPL_ASSERT_NOT(( mock::detail::is_functor< declared_but_not_defined, int > ));
template< typename T > template< typename T >
void is_functor( T ) void is_functor( T )
{ {
BOOST_MPL_ASSERT(( mock::detail::is_functor< T > )); BOOST_MPL_ASSERT(( mock::detail::is_functor< T, int > ));
}
template< typename T >
void is_not_functor( T )
{
BOOST_MPL_ASSERT_NOT(( mock::detail::is_functor< T, int > ));
} }
void f0() {} void f0() {}
@ -35,6 +40,11 @@ namespace
bool f2( std::string, int ) { return false; } bool f2( std::string, int ) { return false; }
} }
BOOST_AUTO_TEST_CASE( data_is_not_functor )
{
is_not_functor( 42 );
}
BOOST_AUTO_TEST_CASE( function_is_functor ) BOOST_AUTO_TEST_CASE( function_is_functor )
{ {
is_functor( f0 ); is_functor( f0 );
@ -63,12 +73,11 @@ BOOST_AUTO_TEST_CASE( std_bind_first_is_functor )
namespace namespace
{ {
struct unary_functor0 : public std::unary_function< void, void > struct unary_functor0 : public std::unary_function< void, void >
{ {};
};
struct unary_functor1 : public std::unary_function< int, void > struct unary_functor1 : public std::unary_function< int, void >
{ {};
};
} }
BOOST_AUTO_TEST_CASE( std_unary_functor_is_functor ) BOOST_AUTO_TEST_CASE( std_unary_functor_is_functor )
{ {
is_functor( unary_functor0() ); is_functor( unary_functor0() );
@ -105,6 +114,7 @@ namespace
typedef void result_type; typedef void result_type;
}; };
} }
BOOST_AUTO_TEST_CASE( class_with_result_type_is_functor ) BOOST_AUTO_TEST_CASE( class_with_result_type_is_functor )
{ {
is_functor( result_type_functor() ); is_functor( result_type_functor() );
@ -121,7 +131,20 @@ namespace
}; };
}; };
} }
BOOST_AUTO_TEST_CASE( class_with_sig_is_functor ) BOOST_AUTO_TEST_CASE( class_with_sig_is_functor )
{ {
is_functor( sig_functor() ); is_functor( sig_functor() );
} }
#if !defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_NO_LAMBDAS)
BOOST_AUTO_TEST_CASE( cxx11_lambda_is_functor )
{
is_not_functor( []() {} );
is_functor( []( int ) {} );
is_not_functor( []( const std::string&, int ) {} );
is_not_functor( []( int, const std::string& ) {} );
}
#endif

View file

@ -9,6 +9,7 @@
#ifndef MOCK_CONFIG_HPP_INCLUDED #ifndef MOCK_CONFIG_HPP_INCLUDED
#define MOCK_CONFIG_HPP_INCLUDED #define MOCK_CONFIG_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp> #include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/comparison/less.hpp> #include <boost/preprocessor/comparison/less.hpp>
@ -48,4 +49,8 @@
# endif # endif
#endif #endif
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_DECLTYPE)
# define MOCK_DECLTYPE
#endif
#endif // MOCK_CONFIG_HPP_INCLUDED #endif // MOCK_CONFIG_HPP_INCLUDED

View file

@ -9,9 +9,11 @@
#ifndef MOCK_IS_FUNCTOR_HPP_INCLUDED #ifndef MOCK_IS_FUNCTOR_HPP_INCLUDED
#define MOCK_IS_FUNCTOR_HPP_INCLUDED #define MOCK_IS_FUNCTOR_HPP_INCLUDED
#include "../config.hpp"
#include <boost/function_types/is_callable_builtin.hpp> #include <boost/function_types/is_callable_builtin.hpp>
#include <boost/type_traits/detail/yes_no_type.hpp>
#include <boost/utility/declval.hpp>
#include <boost/mpl/has_xxx.hpp> #include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/or.hpp> #include <boost/mpl/or.hpp>
namespace mock namespace mock
@ -22,10 +24,33 @@ namespace detail
BOOST_MPL_HAS_XXX_TEMPLATE_DEF( sig ) BOOST_MPL_HAS_XXX_TEMPLATE_DEF( sig )
BOOST_MPL_HAS_XXX_TEMPLATE_DEF( result ) BOOST_MPL_HAS_XXX_TEMPLATE_DEF( result )
#ifdef MOCK_DECLTYPE
template< typename T, typename P >
struct is_callable
{
typedef boost::type_traits::yes_type yes_type;
typedef boost::type_traits::no_type no_type;
template< typename T > template< typename T >
static yes_type check(
decltype( boost::declval< T >()( boost::declval< P >() ) )* );
template< typename T >
static no_type check( ... );
typedef boost::mpl::bool_<
sizeof( check< T >( 0 ) ) == sizeof( yes_type ) > type;
};
#endif // MOCK_DECLTYPE
template< typename T, typename P >
struct is_functor struct is_functor
: boost::mpl::or_< : boost::mpl::or_<
boost::function_types::is_callable_builtin< T >, boost::function_types::is_callable_builtin< T >,
#ifdef MOCK_DECLTYPE
is_callable< T, P >,
#endif
has_result_type< T >, has_result_type< T >,
has_result< T >, has_result< T >,
has_sig< T > has_sig< T >

View file

@ -84,7 +84,7 @@ namespace mock
template< typename Actual, typename Functor > template< typename Actual, typename Functor >
class matcher< Actual, Functor, class matcher< Actual, Functor,
BOOST_DEDUCED_TYPENAME boost::enable_if< BOOST_DEDUCED_TYPENAME boost::enable_if<
detail::is_functor< Functor > detail::is_functor< Functor, Actual >
>::type >::type
> : public detail::matcher_base< Actual > > : public detail::matcher_base< Actual >
{ {