Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F87552519
static_dispatch.hh
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Oct 13, 08:51
Size
6 KB
Mime Type
text/x-c++
Expires
Tue, Oct 15, 08:51 (2 d)
Engine
blob
Format
Raw Data
Handle
21617177
Attached To
rLIBMULTISCALE LibMultiScale
static_dispatch.hh
View Options
#ifndef __LIBMULTISCALE_AUTOMATIC_CAST_HH__
#define __LIBMULTISCALE_AUTOMATIC_CAST_HH__
#include <any>
#include <iostream>
#include <stdexcept>
#include <tuple>
#include <utility>
//****************************************************************
// apply static functor on tuple
//****************************************************************
#if __cplusplus <= 201402
namespace
detail
{
template
<
class
F
,
class
Tuple
,
std
::
size_t
...
I
>
constexpr
decltype
(
auto
)
apply_impl
(
F
&&
f
,
Tuple
&&
t
,
std
::
index_sequence
<
I
...
>
)
{
return
f
(
std
::
get
<
I
>
(
std
::
forward
<
Tuple
>
(
t
))...);
}
}
// namespace detail
template
<
class
F
,
class
Tuple
>
constexpr
decltype
(
auto
)
apply
(
F
&&
f
,
Tuple
&&
t
)
{
return
detail
::
apply_impl
(
std
::
forward
<
F
>
(
f
),
std
::
forward
<
Tuple
>
(
t
),
std
::
make_index_sequence
<
std
::
tuple_size
<
std
::
remove_reference_t
<
Tuple
>>::
value
>
{});
}
#else
#define apply std::apply
#endif
//****************************************************************
// casting of objects
//****************************************************************
template
<
typename
possible_types
,
int
n
>
struct
_cpp_dynamic_cast
{
template
<
typename
CastFunctor
,
typename
AfterCastFunctor
,
typename
Arg
>
static
void
cast
(
CastFunctor
&
cast_functor
,
AfterCastFunctor
&
call_after_cast
,
Arg
&
arg
)
{
using
_type
=
std
::
remove_pointer_t
<
std
::
decay_t
<
std
::
tuple_element_t
<
n
,
possible_types
>>>
;
if
(
auto
*
ptr
=
cast_functor
.
template
cast
<
_type
>
(
arg
))
{
call_after_cast
(
*
ptr
);
return
;
}
_cpp_dynamic_cast
<
possible_types
,
n
-
1
>::
template
cast
(
cast_functor
,
call_after_cast
,
arg
);
}
};
template
<
typename
possible_types
>
struct
_cpp_dynamic_cast
<
possible_types
,
-
1
>
{
template
<
typename
CastFunctor
,
typename
AfterCastFunctor
,
typename
Arg
>
static
void
cast
(
CastFunctor
&
,
AfterCastFunctor
&
,
Arg
&
)
{
throw
std
::
bad_cast
();
}
};
template
<
typename
...
Args
>
void
toto
(
std
::
tuple
<
Args
...
>
)
{}
template
<
typename
possible_types
,
typename
CastFunctor
,
typename
AfterCastFunctor
,
typename
Arg
>
void
cpp_dynamic_cast
(
CastFunctor
&
cast_functor
,
AfterCastFunctor
&
call_after_cast
,
Arg
&
arg
)
{
constexpr
size_t
N
=
std
::
tuple_size
<
possible_types
>::
value
;
_cpp_dynamic_cast
<
possible_types
,
N
-
1
>::
cast
(
cast_functor
,
call_after_cast
,
arg
);
}
/* --------------------------------------------------------------------- */
template
<
int
argument_position
,
typename
PossibleTypes
,
typename
ArgumentsTuple
,
typename
ArgumentsCastedTuple
>
struct
Dispatch
{
template
<
typename
Functor
,
typename
CastFunctor
>
static
void
dispatch
(
Functor
&
functor
,
CastFunctor
&
cast_functor
,
ArgumentsTuple
args
,
ArgumentsCastedTuple
args_casted
)
{
using
possible_types
=
std
::
tuple_element_t
<
argument_position
,
PossibleTypes
>
;
auto
arg
=
std
::
get
<
argument_position
>
(
args
);
// functor that will be called after resolving
// the dynamic cast of the current argument
// => It will proceed to the next argument
auto
&&
call_after_cast
=
[
&
](
auto
&&
casted_object
)
{
auto
tup
=
std
::
forward_as_tuple
(
casted_object
);
auto
new_args_casted
=
std
::
tuple_cat
(
tup
,
args_casted
);
Dispatch
<
argument_position
-
1
,
PossibleTypes
,
ArgumentsTuple
,
decltype
(
new_args_casted
)
>::
dispatch
(
functor
,
cast_functor
,
args
,
new_args_casted
);
};
cpp_dynamic_cast
<
possible_types
>
(
cast_functor
,
call_after_cast
,
arg
);
}
};
// specialization for the end of recursion: all args have been dynamic casted
// need to call the function
template
<
typename
PossibleTypes
,
typename
ArgumentsTuple
,
typename
ArgumentsCastedTuple
>
struct
Dispatch
<-
1
,
PossibleTypes
,
ArgumentsTuple
,
ArgumentsCastedTuple
>
{
template
<
typename
Functor
,
typename
CastFunctor
>
static
void
dispatch
(
Functor
&
functor
,
CastFunctor
&
,
ArgumentsTuple
,
ArgumentsCastedTuple
args_formatted
)
{
apply
([
&
](
auto
&
...
args
)
{
functor
(
args
...);
},
args_formatted
);
}
};
template
<
typename
PossibleTypes
,
typename
CastFunctor
,
typename
Functor
,
typename
...
Args
>
void
_static_dispatch
(
Functor
func
,
Args
&
...
args
)
{
auto
arguments_tuple
=
std
::
make_tuple
(
&
args
...);
constexpr
size_t
N
=
std
::
tuple_size
<
decltype
(
arguments_tuple
)
>::
value
;
auto
cast_functor
=
CastFunctor
{};
Dispatch
<
N
-
1
,
PossibleTypes
,
decltype
(
arguments_tuple
),
std
::
tuple
<>>::
dispatch
(
func
,
cast_functor
,
arguments_tuple
,
std
::
tuple
<>
{});
}
/* --------------------------------------------------------------------- */
// DECORATION POSSIBILITY
/* --------------------------------------------------------------------- */
#define _Args(...) __VA_ARGS__
#define STRIP_PARENS(X) X
#define STATIC_DISPATCH_DECLARE(NAME, POS_TYPES) \
template <typename... Args> void NAME##_dispatch(Args &&... args) { \
using possible_types = std::tuple<STRIP_PARENS(_Args POS_TYPES)>; \
_static_dispatch<possible_types, _simple_cast>( \
[&](auto &&... args) { NAME(std::forward<decltype(args)>(args)...); }, \
std::forward<Args>(args)...); \
}
#define STATIC_CLASS_DISPATCH_DECLARE(NAME, POS_TYPES) \
template <typename... Args> void NAME##_dispatch(Args &&... args) { \
using possible_types = std::tuple<STRIP_PARENS(_Args POS_TYPES)>; \
_static_dispatch<possible_types, _simple_cast>( \
[&](auto &&... args) { NAME(std::forward<decltype(args)>(args)...); }, \
std::forward<Args>(args)...); \
} \
friend void _instanciate_static_class_dispatch();
struct
_simple_cast
{
template
<
typename
type
,
typename
Arg
>
type
*
cast
(
Arg
&
arg
)
{
if
(
auto
*
ptr
=
dynamic_cast
<
type
*>
(
arg
))
{
return
ptr
;
}
return
nullptr
;
}
};
/* --------------------------------------------------------------------- */
#endif
// __LIBMULTISCALE_AUTOMATIC_CAST_HH__
Event Timeline
Log In to Comment