From e1800140dbfcdf44ef74e3bf1c5c78ff18c8f951 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Fri, 14 Jun 2019 08:41:52 +0200 Subject: [PATCH] add and use constexpr_switch --- .../src/common/AbstractionHelpers.hpp | 23 +++++------- alib2std/src/extensions/utility.hpp | 16 ++++++++ alib2std/test-src/extensions/UtilityTest.cpp | 37 +++++++++++++++++++ 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/alib2abstraction/src/common/AbstractionHelpers.hpp b/alib2abstraction/src/common/AbstractionHelpers.hpp index 15a7660123..4a86d5dec0 100644 --- a/alib2abstraction/src/common/AbstractionHelpers.hpp +++ b/alib2abstraction/src/common/AbstractionHelpers.hpp @@ -35,22 +35,17 @@ constexpr decltype ( auto ) apply ( F && f, Tuple && t ) { } template < class ... Params > -struct CheckInput; +struct CheckInput { + static bool checkInput ( const std::shared_ptr < OperationAbstraction > & operation, unsigned index ) { + bool res = false; -template < > -struct CheckInput < > { - static bool checkInput ( const std::shared_ptr < OperationAbstraction > &, unsigned ) { - throw std::logic_error ( "Out of types to check" ); - } -}; + auto lambda = [ & ] ( auto I ) { + res = ( bool ) std::dynamic_pointer_cast < std::decay_t < std::tuple_element_t < decltype ( I )::value, std::tuple < Params ... > > > > ( operation->getProxyAbstraction ( ) ); + }; -template < class Param, class ... Params > -struct CheckInput < Param, Params ... > { - static bool checkInput ( const std::shared_ptr < OperationAbstraction > & operation, unsigned index ) { - if ( index == 0 ) - return ( bool ) std::dynamic_pointer_cast < typename std::decay < Param >::type > ( operation->getProxyAbstraction ( ) ); - else - return CheckInput < Params ... >::checkInput ( operation, index - 1 ); + ext::constexpr_switch < sizeof ... ( Params ) > ( index, lambda ); + + return res; } }; diff --git a/alib2std/src/extensions/utility.hpp b/alib2std/src/extensions/utility.hpp index 8782eef5fe..689eb23a2b 100644 --- a/alib2std/src/extensions/utility.hpp +++ b/alib2std/src/extensions/utility.hpp @@ -51,6 +51,22 @@ inline auto move_copy ( const T & param ) { } } +namespace detail { + +template < class F, std::size_t ... Is > +void constexpr_switch ( const std::size_t i, F && f, std::index_sequence < Is ... > ) { + [ ] ( ... ) { } ( + ( i == Is && ( ( void ) std::forward < F > ( f ) . operator ( ) ( std::integral_constant < size_t, Is > ( ) ), false ) ) ... + ); +} + +} // namespace detail + +template < std::size_t N, class F > +void constexpr_switch ( const std::size_t i, F && f ) { + detail::constexpr_switch ( i, std::forward < F > ( f ), std::make_index_sequence < N > { } ); +} + } /* namespace ext */ #endif /* __UTILITY_HPP_ */ diff --git a/alib2std/test-src/extensions/UtilityTest.cpp b/alib2std/test-src/extensions/UtilityTest.cpp index 866d111496..6a77be3d31 100644 --- a/alib2std/test-src/extensions/UtilityTest.cpp +++ b/alib2std/test-src/extensions/UtilityTest.cpp @@ -16,4 +16,41 @@ TEST_CASE ( "Utility", "[unit][std][bits]" ) { ext::ptr_value < Foo > val ( Foo { } ); CHECK ( val->bar ( ) == 1 ); } + + SECTION ( "Constexp switch" ) { + { + auto const t = std::make_tuple(42, 'z', 3.14, 13, 0, "Hello, World!"); + + auto lambda = [ & ] ( auto I ) { + if constexpr ( I == 0 ) + CHECK ( std::get < decltype ( I )::value > ( t ) == 42 ); + else if constexpr ( I == 1 ) + CHECK ( std::get < decltype ( I )::value > ( t ) == 'z' ); + else if constexpr ( I == 2 ) + CHECK ( std::get < decltype ( I )::value > ( t ) == 3.14 ); + else if constexpr ( I == 3 ) + CHECK ( std::get < decltype ( I )::value > ( t ) == 13 ); + else if constexpr ( I == 4 ) + CHECK ( std::get < decltype ( I )::value > ( t ) == 0 ); + else // constexpr ( I == 5 ) + CHECK ( std::get < decltype ( I )::value > ( t ) == std::string ( "Hello, World!" ) ); + }; + + for (std::size_t i = 0; i < std::tuple_size<decltype(t)>::value; ++i) { + ext::constexpr_switch < std::tuple_size<decltype(t)>::value > ( i, lambda ); + } + } + + { + auto const t = std::array<int, 4>{{0,1,2,3}}; + + auto lambda = [ & ] ( auto I ) { + CHECK ( std::get < decltype ( I )::value > ( t ) == I ); + }; + + for (std::size_t i = 0; i < t.size(); ++i) { + ext::constexpr_switch < std::tuple_size<decltype(t)>::value > ( i, lambda ); + } + } + } } -- GitLab