diff --git a/build/vc80/turtle.vcproj b/build/vc80/turtle.vcproj index 542057e..11b973e 100644 --- a/build/vc80/turtle.vcproj +++ b/build/vc80/turtle.vcproj @@ -184,6 +184,10 @@ RelativePath="..\..\src\libraries\turtle\invocation.hpp" > + + diff --git a/build/vc80/turtle_test.vcproj b/build/vc80/turtle_test.vcproj index 7f1f9b2..574846f 100644 --- a/build/vc80/turtle_test.vcproj +++ b/build/vc80/turtle_test.vcproj @@ -208,6 +208,10 @@ RelativePath="..\..\src\tests\turtle_test\invocation_test.cpp" > + + diff --git a/src/libraries/turtle/check.hpp b/src/libraries/turtle/check.hpp index b50e48d..7812db3 100644 --- a/src/libraries/turtle/check.hpp +++ b/src/libraries/turtle/check.hpp @@ -11,8 +11,10 @@ #include "placeholder.hpp" #include "constraint.hpp" +#include "is_functor.hpp" #include "format.hpp" #include +#include #include #include @@ -27,15 +29,28 @@ namespace detail boost::function< bool( Arg ) > functor_type; public: + template< typename F > + explicit check( const F& f, + BOOST_DEDUCED_TYPENAME boost::enable_if< + BOOST_DEDUCED_TYPENAME detail::is_functor< F >::type + >::type* = 0 ) + : functor_( f ) + , desc_ ( "?" ) + { + if( !functor_ ) + std::invalid_argument( "invalid functor" ); + } template< typename T > - explicit check( const T& t ) + explicit check( const T& t, + BOOST_DEDUCED_TYPENAME boost::disable_if< + BOOST_DEDUCED_TYPENAME detail::is_functor< T >::type + >::type* = 0 ) : functor_( equal( t ).functor_ ) , desc_ ( detail::format( t ) ) { if( !functor_ ) std::invalid_argument( "invalid functor" ); } - template< typename Constraint > explicit check( const placeholder< Constraint >& c ) : functor_( c.functor_ ) diff --git a/src/libraries/turtle/is_functor.hpp b/src/libraries/turtle/is_functor.hpp new file mode 100644 index 0000000..6b57ecb --- /dev/null +++ b/src/libraries/turtle/is_functor.hpp @@ -0,0 +1,48 @@ +// +// Copyright Mathieu Champlon 2009 +// +// 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_IS_FUNCTOR_HPP_INCLUDED +#define MOCK_IS_FUNCTOR_HPP_INCLUDED + +#include + +namespace mock +{ +namespace detail +{ + typedef char true_type[2]; + typedef char false_type[1]; + + template< typename T > + true_type& has_result_type_helper( T*, BOOST_DEDUCED_TYPENAME T::result_type* = 0 ) {} + template< typename T > + false_type& has_result_type_helper( T, ... ) {} + + template< typename T > + struct has_result_type + { + static T* t(); + enum { value = sizeof( has_result_type_helper( t() ) ) == sizeof( true_type ) }; + }; + + template< typename T, bool B = has_result_type< T >::value > + struct is_functor + { + typedef BOOST_DEDUCED_TYPENAME boost::function_types::is_callable_builtin< T >::type type; + enum { value = BOOST_DEDUCED_TYPENAME type::value }; + }; + template< typename T > + struct is_functor< T, true > + { + typedef boost::true_type type; + enum { value = true }; + }; +} +} + +#endif // #ifndef MOCK_IS_FUNCTOR_HPP_INCLUDED diff --git a/src/tests/turtle_test/expectation_test.cpp b/src/tests/turtle_test/expectation_test.cpp index 1cd8d12..c6f9a77 100644 --- a/src/tests/turtle_test/expectation_test.cpp +++ b/src/tests/turtle_test/expectation_test.cpp @@ -303,12 +303,12 @@ BOOST_AUTO_TEST_CASE( triggering_an_expectation_with_failing_custom_constraint_t { { mock::expectation< void( int ) > e; - e.expect().with( mock::constraint( &custom_constraint ) ); + e.expect().with( &custom_constraint ); BOOST_CHECK_EXCEPTION_CONTAINS( e( 42 ), "unexpected call" ); } { mock::expectation< int( int, const std::string& ) > e; - e.expect().with( mock::constraint( &custom_constraint ), "actual" ); + e.expect().with( &custom_constraint, "actual" ); BOOST_CHECK_EXCEPTION_CONTAINS( e( 42, "actual" ), "unexpected call" ); } } @@ -655,7 +655,7 @@ BOOST_AUTO_TEST_CASE( expectation_can_be_serialized_to_be_human_readable ) } { mock::expectation< void( int ) > e( "my expectation" ); - e.expect().once().with( mock::constraint( &custom_constraint ) ); + e.expect().once().with( &custom_constraint ); std::stringstream s; s << e; const std::string expected = "my expectation\n" diff --git a/src/tests/turtle_test/is_functor_test.cpp b/src/tests/turtle_test/is_functor_test.cpp new file mode 100644 index 0000000..efa3098 --- /dev/null +++ b/src/tests/turtle_test/is_functor_test.cpp @@ -0,0 +1,59 @@ +// +// Copyright Mathieu Champlon 2009 +// +// 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) +// + +#include +#include +#include + +#include +#define BOOST_LIB_NAME boost_unit_test_framework +#include + +namespace +{ + template< typename T > + void check( T ) + { + BOOST_STATIC_ASSERT(( mock::detail::is_functor< T >::value )); + } + + void f0 () {} + bool f1( int ) { return false; } + + struct s + { + typedef void result_type; + }; +} + +BOOST_AUTO_TEST_CASE( function_is_functor ) +{ + check( f0 ); + check( f1 ); +} + +BOOST_AUTO_TEST_CASE( function_pointer_is_functor ) +{ + check( &f0 ); + check( &f1 ); +} + +BOOST_AUTO_TEST_CASE( boost_bind_is_functor ) +{ + check( boost::bind( &f0 ) ); +} + +BOOST_AUTO_TEST_CASE( boost_function_is_functor ) +{ + check( boost::function< void() >() ); +} + +BOOST_AUTO_TEST_CASE( class_with_result_type_is_functor ) +{ + check( s() ); +}