diff --git a/alib2std/src/extensions/type_traits.hpp b/alib2std/src/extensions/type_traits.hpp index 7161c28094ebdcee079ddb21ea33c0ddb6929bb8..12756c1aeb2fa9c22b0a307c17737365783a372e 100644 --- a/alib2std/src/extensions/type_traits.hpp +++ b/alib2std/src/extensions/type_traits.hpp @@ -53,6 +53,41 @@ namespace ext { static const bool value = sizeof(Yes) == sizeof(has_clone::test((typename std::decay<T>::type*)0)); }; + /** + * \brief + * Positive supports test implementation. The test is designed to detect call availability on callable F with parameters Ts ... + * + * \tparam F the type of callable + * \tparam Ts ... call parameter types + * + * \returns std::true_type + */ + template < class F, class ... Ts, typename = decltype ( std::declval < F > ( ) ( std::declval < Ts > ( ) ... ) ) > + std::true_type supports_test ( const F &, const Ts & ... ); + + /** + * \brief + * Negative supports test implementation. The test is designed to be callback when the positive test failed. + * + * \returns std::false_type + */ + std::false_type supports_test ( ... ); + + /** + * Base implementation of the call test support. + */ + template < class > struct supports; + + /** + * Specialisation of the call test support for F type be a callable. + * + * \tparam F the type of callable + * \tparam Ts ... call parameter types + * + * If the call with parameter types Ts ... is possible on callable F, the class provides a value of type true, othervise a false value filed is provided. + */ + template < class F, class ... Ts > struct supports < F ( Ts ... ) > : decltype ( supports_test ( std::declval < F > ( ), std::declval < Ts > ( ) ... ) ) { }; + // ---------------------------------------------------------------------------------------------------- /** diff --git a/alib2std/test-src/extensions/TypeTraitsTest.cpp b/alib2std/test-src/extensions/TypeTraitsTest.cpp index 7917890025943bfa2d69545dad5d4c2e12d3b090..d92457fcf0a82f81768611a953a4275950169724 100644 --- a/alib2std/test-src/extensions/TypeTraitsTest.cpp +++ b/alib2std/test-src/extensions/TypeTraitsTest.cpp @@ -30,3 +30,15 @@ void TypeTraitsTest::testTypeNames() { CPPUNIT_ASSERT ( ext::to_string < Bar > ( ) == "Bar" ); CPPUNIT_ASSERT ( ext::to_string < int > ( ) == "int" ); } + +bool operator < ( const Foo &, int ) { + return false; +} + +void TypeTraitsTest::testSupports() { + CPPUNIT_ASSERT ( ext::supports < std::less < > ( int, int ) >::value == true ); + CPPUNIT_ASSERT ( ext::supports < std::less < > ( unsigned, int ) >::value == true ); + CPPUNIT_ASSERT ( ext::supports < std::less < > ( double, char ) >::value == true ); + CPPUNIT_ASSERT ( ext::supports < std::less < > ( Foo, char ) >::value == true ); + CPPUNIT_ASSERT ( ext::supports < std::less < > ( Foo, Foo ) >::value == false ); +} diff --git a/alib2std/test-src/extensions/TypeTraitsTest.h b/alib2std/test-src/extensions/TypeTraitsTest.h index 0c3ed628d8e1235d52c4a9b9fba12abb551f442d..3ef045b9ec8a156d372468b29110a3dd953051be 100644 --- a/alib2std/test-src/extensions/TypeTraitsTest.h +++ b/alib2std/test-src/extensions/TypeTraitsTest.h @@ -7,6 +7,7 @@ class TypeTraitsTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( TypeTraitsTest ); CPPUNIT_TEST( testTypeInPack ); CPPUNIT_TEST( testTypeNames ); + CPPUNIT_TEST( testSupports ); CPPUNIT_TEST_SUITE_END(); public: @@ -15,6 +16,7 @@ public: void testTypeInPack(); void testTypeNames(); + void testSupports(); }; #endif // TYPE_TRAITS_TEST_H_