Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F70969263
auto_arguments.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
Mon, Jul 8, 13:14
Size
8 KB
Mime Type
text/x-c++
Expires
Wed, Jul 10, 13:14 (1 d, 21 h)
Engine
blob
Format
Raw Data
Handle
18891697
Attached To
rLIBMULTISCALE LibMultiScale
auto_arguments.hh
View Options
#ifndef __AUTO_ARGUMENTS_HH__
#define __AUTO_ARGUMENTS_HH__
/*****************************************************************/
#include "auto_argument.hh"
#include <functional>
#include <iostream>
/*****************************************************************/
namespace
AutoDispatch
{
/*****************************************************************/
struct
dispatch
{};
/*****************************************************************/
template
<
int
n_arg
>
struct
apply_arguments
{
template
<
typename
Functor
,
typename
Arguments
>
static
decltype
(
auto
)
apply
(
Functor
&&
f
,
Arguments
&
args
)
{
apply_arguments
::
apply
(
f
,
args
,
std
::
make_tuple
<>
());
}
template
<
typename
Functor
,
typename
Arguments
,
typename
CastedArguments
>
static
decltype
(
auto
)
apply
(
Functor
&&
f
,
Arguments
&
args
,
CastedArguments
&&
casted_arguments
)
{
auto
&&
arg
=
args
.
template
get
<
n_arg
>
();
try
{
arg
.
visit
([
&
](
auto
&&
a
)
{
auto
&&
new_args
=
std
::
tuple_cat
(
std
::
forward_as_tuple
(
a
),
casted_arguments
);
apply_arguments
<
n_arg
-
1
>::
apply
(
f
,
args
,
new_args
);
});
}
catch
(
bad_argument_cast
&
e
)
{
bad_argument_cast
ex
;
ex
.
str
=
"Cannot cast argument #"
+
std
::
to_string
(
n_arg
)
+
" => "
+
e
.
str
;
throw
ex
;
}
}
};
template
<>
struct
apply_arguments
<-
1
>
{
template
<
typename
Functor
,
typename
Arguments
,
typename
CastedArguments
>
static
decltype
(
auto
)
apply
(
Functor
&&
f
,
Arguments
&
,
CastedArguments
&&
casted_arguments
)
{
std
::
apply
(
f
,
casted_arguments
);
}
};
/*****************************************************************/
template
<
typename
...
possible_types
>
class
arguments
{
using
_args
=
typename
std
::
tuple
<
argument
<
possible_types
>
...
>
;
static
constexpr
std
::
size_t
size
=
std
::
tuple_size
<
_args
>
();
public
:
arguments
()
=
default
;
template
<
typename
...
Ts
>
arguments
(
Ts
&&
...
a
)
{
args
=
std
::
forward_as_tuple
(
a
...);
}
template
<
typename
F
>
decltype
(
auto
)
visit
(
F
&&
f
)
{
apply_arguments
<
size
-
1
>::
apply
(
f
,
*
this
);
}
template
<
int
n
>
decltype
(
auto
)
get
()
{
return
std
::
get
<
n
>
(
args
);
}
private
:
_args
args
;
};
/*****************************************************************/
template
<
typename
possible_types
,
typename
...
Tup
>
struct
create_arguments_and_visit
{
template
<
typename
F
,
typename
...
Ts
>
static
void
visit
(
F
&&
f
,
Ts
&&
...
v
)
{
arguments
<
Tup
...
>
args
(
std
::
forward
<
Ts
>
(
v
)...);
args
.
visit
(
f
);
}
};
/*****************************************************************/
template
<
typename
...
possible_types
>
struct
create_arguments_and_visit
<
std
::
tuple
<
possible_types
...
>
,
dispatch
>
{
template
<
typename
F
,
typename
...
Ts
>
static
void
visit
(
F
&&
f
,
Ts
&&
...
v
)
{
static_assert
(
std
::
tuple_size_v
<
std
::
tuple
<
possible_types
...
>>>
0
,
"For automatic dispatch the decoration "
"DECORATE_FUNCTION_DISPATCH must define valid types"
);
arguments
<
possible_types
...
>
args
(
std
::
forward
<
Ts
>
(
v
)...);
args
.
visit
(
f
);
}
};
/*****************************************************************/
template
<
typename
T
>
struct
add_pointer_to_tuple
;
template
<
typename
...
Ts
>
struct
add_pointer_to_tuple
<
std
::
tuple
<
Ts
...
>>
{
using
type
=
std
::
tuple
<
std
::
add_pointer_t
<
std
::
decay_t
<
Ts
>>
...
>
;
};
template
<
typename
T
>
struct
remove_pointer_to_tuple
;
template
<
typename
...
Ts
>
struct
remove_pointer_to_tuple
<
std
::
tuple
<
Ts
...
>>
{
using
type
=
typename
std
::
tuple
<
std
::
remove_pointer_t
<
std
::
decay_t
<
Ts
>>
...
>
;
};
template
<
class
F
,
class
Tuple
,
std
::
size_t
...
I
>
void
apply_ptr
(
F
&&
f
,
Tuple
&&
t
,
std
::
index_sequence
<
I
...
>
&&
)
{
return
f
(
std
::
get
<
I
>
(
t
)...);
}
template
<
typename
T
>
struct
apply_tuple_types_impl
{};
template
<
typename
...
Ts
>
struct
apply_tuple_types_impl
<
std
::
tuple
<
Ts
...
>>
{
template
<
typename
F
>
static
void
apply
(
F
&&
f
)
{
std
::
tuple
<
typename
add_pointer_to_tuple
<
Ts
>::
type
...
>
args
;
apply_ptr
(
std
::
forward
<
F
>
(
f
),
args
,
std
::
make_index_sequence
<
sizeof
...(
Ts
)
>
{});
}
};
#define apply_tuple_types(fname, _tuple, ...) \
AutoDispatch::apply_tuple_types_impl<_tuple>::apply([&](auto... Ts) { \
fname<typename AutoDispatch::remove_pointer_to_tuple<decltype( \
Ts)>::type...>(__VA_ARGS__); \
});
/*****************************************************************/
template
<
typename
T
>
struct
make_it_tuple
{
using
type
=
std
::
tuple
<
T
>
;
};
template
<
typename
...
T
>
struct
make_it_tuple
<
std
::
tuple
<
T
...
>>
{
using
type
=
std
::
tuple
<
T
...
>
;
};
/*****************************************************************/
template
<
typename
...
T
>
struct
_or_impl
;
template
<
typename
T
,
typename
...
T2
>
struct
_or_impl
<
T
,
T2
...
>
{
using
type_tail
=
typename
_or_impl
<
T2
...
>::
type
;
using
head
=
typename
make_it_tuple
<
T
>::
type
;
using
type
=
decltype
(
std
::
tuple_cat
(
std
::
declval
<
head
>
(),
std
::
declval
<
type_tail
>
()));
};
template
<>
struct
_or_impl
<>
{
using
type
=
std
::
tuple
<>
;
};
template
<
typename
...
T
>
using
_or
=
typename
_or_impl
<
T
...
>::
type
;
/*****************************************************************/
template
<
typename
...
T
>
struct
_tuple_params_impl
;
template
<
typename
T
,
typename
...
T2
>
struct
_tuple_params_impl
<
T
,
T2
...
>
{
using
head
=
std
::
tuple
<
typename
make_it_tuple
<
T
>::
type
>
;
using
type_tail
=
typename
_tuple_params_impl
<
T2
...
>::
type
;
using
type
=
decltype
(
std
::
tuple_cat
(
std
::
declval
<
head
>
(),
std
::
declval
<
type_tail
>
()));
};
template
<>
struct
_tuple_params_impl
<>
{
using
type
=
std
::
tuple
<>
;
};
template
<
typename
...
T
>
using
_tuple_params
=
typename
_tuple_params_impl
<
T
...
>::
type
;
template
<
typename
...
T
>
using
_params
=
std
::
tuple
<
T
...
>
;
/*****************************************************************/
template
<
typename
T
,
typename
Tuple
>
struct
has_type
;
template
<
typename
T
>
struct
has_type
<
T
,
std
::
tuple
<>>
:
std
::
false_type
{};
template
<
typename
T
,
typename
U
,
typename
...
Ts
>
struct
has_type
<
T
,
std
::
tuple
<
U
,
Ts
...
>>
:
has_type
<
T
,
std
::
tuple
<
Ts
...
>>
{};
template
<
typename
T
,
typename
...
Ts
>
struct
has_type
<
T
,
std
::
tuple
<
T
,
Ts
...
>>
:
std
::
true_type
{};
template
<
typename
Ts
,
typename
Tuples
>
void
debug
(
std
::
ostream
&
os
)
{
os
<<
"has_type: "
<<
Argument
::
demangle
(
typeid
(
Ts
).
name
())
<<
", "
<<
Argument
::
demangle
(
typeid
(
Tuples
).
name
())
<<
" => "
<<
has_type
<
Ts
,
Tuples
>::
value
<<
std
::
endl
;
}
template
<
typename
Ts
,
typename
Tuples
>
struct
param_has_types
;
template
<
typename
...
Ts
,
typename
...
Tuples
>
struct
param_has_types
<
std
::
tuple
<
Ts
...
>
,
std
::
tuple
<
Tuples
...
>>
{
constexpr
static
bool
value
=
true
and
(
has_type
<
std
::
decay_t
<
Ts
>
,
Tuples
>::
value
and
...);
// static void get_tests() {
// std::cout << Argument::demangle(typeid(std::tuple<Ts...>).name())
// << std::endl;
// (debug<Ts, Tuples>(std::cout), ...);
// }
// using types = std::tuple<std::pair<Ts *, Tuples *>...>;
};
template
<
typename
paramTypes
,
typename
...
possible_types
>
using
enable_if_type
=
std
::
enable_if_t
<
param_has_types
<
paramTypes
,
_tuple_params
<
possible_types
...
>>::
value
>
;
template
<
typename
paramTypes
,
typename
...
possible_types
>
using
enable_if_not_type
=
std
::
enable_if_t
<
not
param_has_types
<
paramTypes
,
_tuple_params
<
possible_types
...
>>::
value
>
;
/*****************************************************************/
// functions decorators
/*****************************************************************/
#define DECORATE_FUNCTION_DISPATCH(fname, ...) \
using fname##_possible_types = std::tuple<__VA_ARGS__>; \
void fname##_force_instanciation(); \
template <typename... Tup, typename... Ts> \
std::enable_if_t<sizeof...(Tup) != 0> fname(Ts &&... v) { \
AutoDispatch::create_arguments_and_visit<fname##_possible_types, Tup...>:: \
visit([&](auto &&... a) { fname(a...); }, v...); \
}
#define INSTANCIATE_DISPATCH(fname) \
void fname##_force_instanciation() { \
constexpr int sz = std::tuple_size_v<fname##_possible_types>; \
std::array<AutoDispatch::Argument, sz> args; \
std::apply( \
[&](auto &&... a) { \
apply_tuple_types(fname, fname##_possible_types, a...); \
}, \
args); \
}
}
// namespace AutoDispatch
#endif
//__AUTO_ARGUMENTS_HH__
Event Timeline
Log In to Comment