Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Tiago Peixoto
graph-tool
Commits
e67702c9
Commit
e67702c9
authored
Jul 10, 2020
by
Jeff Trull
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use lambdas and pack expansion to reduce template instantiations in action_dispatch
parent
66d1db43
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
85 additions
and
65 deletions
+85
-65
src/graph/graph_filtering.hh
src/graph/graph_filtering.hh
+82
-5
src/graph/mpl_nested_loop.hh
src/graph/mpl_nested_loop.hh
+3
-60
No files found.
src/graph/graph_filtering.hh
View file @
e67702c9
...
...
@@ -423,9 +423,83 @@ struct action_wrap
Action
_a
;
};
// this takes a functor and type ranges and iterates through the type
// combinations when called with boost::any parameters, and calls the correct
// function
//
// action_dispatch machinery
//
// a lightweight class for holding a list of types
template
<
class
...
T
>
struct
typelist
{};
template
<
class
...
T
>
constexpr
auto
to_typelist
(
std
::
tuple
<
T
...
>
)
->
typelist
<
T
...
>
;
template
<
class
Tuple
>
using
to_typelist_t
=
decltype
(
to_typelist
(
std
::
declval
<
Tuple
>
()));
// handling one typelist/value
// select a binding from the current list
template
<
class
F
,
// function to bind
class
...
Ts
,
// current typelist
class
...
TRS
,
// remaining typelists
class
Arg
,
class
...
Args
>
bool
dispatch_loop
(
F
f
,
typelist
<
typelist
<
Ts
...
>
,
TRS
...
>
,
Arg
&&
arg
,
Args
&&
...
args
)
// remaining args
{
using
namespace
boost
::
mpl
;
// determine which one of the Ts we are looking at
// then recurse with the first argument of F bound accordingly
void
*
farg
;
// pointer to extracted value from boost::any
// we always will know what its type is
if
constexpr
(
sizeof
...(
TRS
)
==
0
)
{
// just one argument remains to be bound
return
// iterate over types, trying each
(((
farg
=
boost
::
any_cast
<
Ts
>
(
&
arg
))
?
(
f
(
*
static_cast
<
Ts
*>
(
farg
)),
true
)
// try reference_wrapper instead
:
((
farg
=
boost
::
any_cast
<
std
::
reference_wrapper
<
Ts
>>
(
&
arg
))
?
(
f
(
static_cast
<
std
::
reference_wrapper
<
Ts
>*>
(
farg
)
->
get
()),
true
)
:
false
))
||
...);
}
else
{
// helper function for setting up recursion
auto
dl
=
[
f
=
std
::
move
(
f
)](
auto
*
a
,
// extracted value from boost::any
auto
&&
...
args
)
// boost::any's yet to be processed
{
// create the new F with N-1 arguments
return
dispatch_loop
([
f
=
std
::
move
(
f
),
a
](
auto
&&
...
fargs
){
f
(
*
a
,
std
::
forward
<
decltype
(
fargs
)
>
(
fargs
)...);
},
typelist
<
TRS
...
>
{},
std
::
forward
<
decltype
(
args
)
>
(
args
)...);
};
return
(((
farg
=
boost
::
any_cast
<
Ts
>
(
&
arg
))
?
dl
(
static_cast
<
Ts
*>
(
farg
),
std
::
forward
<
Args
>
(
args
)...)
:
((
farg
=
boost
::
any_cast
<
std
::
reference_wrapper
<
Ts
>>
(
&
arg
))
?
dl
(
&
static_cast
<
std
::
reference_wrapper
<
Ts
>*>
(
farg
)
->
get
(),
std
::
forward
<
Args
>
(
args
)...)
:
false
))
||
...);
// iterate over Ts...
}
}
// this takes a functor and type ranges, locates the correct combination
// from the boost::any parameters, and calls the correct function
template
<
class
Action
,
class
Wrap
,
class
...
TRS
>
struct
action_dispatch
{
...
...
@@ -434,8 +508,11 @@ struct action_dispatch
template
<
class
...
Args
>
void
operator
()(
Args
&&
...
args
)
const
{
bool
found
=
boost
::
mpl
::
nested_for_each
<
TRS
...
>
(
_a
,
std
::
forward
<
Args
>
(
args
)...);
using
namespace
boost
::
mpl
;
bool
found
=
dispatch_loop
(
_a
,
typelist
<
to_typelist_t
<
to_tuple_t
<
TRS
>>
...
>
{},
std
::
forward
<
Args
>
(
args
)...);
if
(
!
found
)
{
std
::
vector
<
const
std
::
type_info
*>
args_t
=
{(
&
(
args
).
type
())...};
...
...
src/graph/mpl_nested_loop.hh
View file @
e67702c9
...
...
@@ -63,55 +63,6 @@ namespace mpl
// of arguments according to the called types. If the cast is successful, the
// function will be called with those types, and true will be returned.
template
<
class
Action
,
std
::
size_t
N
>
struct
all_any_cast
{
all_any_cast
(
Action
a
,
std
::
array
<
any
*
,
N
>&
args
)
:
_a
(
a
),
_args
(
args
)
{}
template
<
class
...
Ts
>
[[
gnu
::
always_inline
]]
bool
operator
()(
Ts
*
...
vs
)
const
{
return
dispatch
(
std
::
make_index_sequence
<
sizeof
...(
Ts
)
>
(),
vs
...);
}
template
<
class
T
>
T
*
try_any_cast
(
boost
::
any
&
a
)
const
{
T
*
t
=
any_cast
<
T
>
(
&
a
);
if
(
t
!=
nullptr
)
return
t
;
std
::
reference_wrapper
<
T
>*
tr
=
any_cast
<
std
::
reference_wrapper
<
T
>>
(
&
a
);
if
(
tr
!=
nullptr
)
return
&
(
tr
->
get
());
return
nullptr
;
}
template
<
std
::
size_t
...
Idx
,
class
...
Ts
>
[[
gnu
::
always_inline
]]
bool
dispatch
(
std
::
index_sequence
<
Idx
...
>
,
Ts
*
...)
const
{
static_assert
(
sizeof
...(
Idx
)
==
N
,
"all_any_cast: wrong number of arguments"
);
std
::
tuple
<
std
::
add_pointer_t
<
Ts
>
...
>
args
;
if
(((
std
::
get
<
Idx
>
(
args
)
=
try_any_cast
<
Ts
>
(
*
_args
[
Idx
]))
&&
...))
{
// successful set of casts. Dereference and call action.
std
::
apply
([
this
](
auto
*
...
arg
){
_a
(
*
arg
...);
},
args
);
return
true
;
}
return
false
;
}
Action
_a
;
std
::
array
<
any
*
,
N
>&
_args
;
};
// recursion-free variadic version of for_each
template
<
class
...
>
struct
for_each_variadic
;
...
...
@@ -143,6 +94,9 @@ struct to_tuple
to_tuple_imp
<
mpl
::
_1
,
mpl
::
_2
>>::
type
type
;
};
template
<
class
Seq
>
using
to_tuple_t
=
typename
to_tuple
<
Seq
>::
type
;
// nested type loops via variadic templates
template
<
class
...
>
...
...
@@ -179,17 +133,6 @@ struct inner_loop<Action, std::tuple<Ts...>, TR1, TRS...>
// final function
template
<
class
TR1
,
class
...
TRS
,
class
Action
,
class
...
Args
>
bool
nested_for_each
(
Action
a
,
Args
&&
...
args
)
{
std
::
array
<
any
*
,
sizeof
...(
args
)
>
as
{{
&
args
...}};
auto
b
=
all_any_cast
<
Action
,
sizeof
...(
args
)
>
(
a
,
as
);
typedef
decltype
(
b
)
action_t
;
typedef
typename
to_tuple
<
TR1
>::
type
tr_tuple
;
typedef
inner_loop
<
action_t
,
std
::
tuple
<>
,
TRS
...
>
inner_loop_t
;
return
for_each_variadic
<
inner_loop_t
,
tr_tuple
>
()(
inner_loop_t
(
b
));
}
template
<
class
TR1
,
class
...
TRS
,
class
Action
>
void
nested_for_each
(
Action
a
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment