Skip to content
Snippets Groups Projects
Commit e1800140 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

add and use constexpr_switch

parent ee50d56f
No related branches found
No related tags found
No related merge requests found
......@@ -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;
}
};
 
......
......@@ -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_ */
......@@ -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 );
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment