Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Tiago Peixoto
graph-tool
Commits
7a84d0f3
Commit
7a84d0f3
authored
May 31, 2014
by
Tiago Peixoto
Browse files
Switch to variadic template implementation of mpl_nested_loop() and run_action()
parent
c212db96
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/graph/correlations/graph_avg_correlations_combined.cc
View file @
7a84d0f3
...
...
@@ -46,7 +46,8 @@ get_vertex_avg_combined_correlation(GraphInterface& gi,
(
avg
,
dev
,
bins
,
ret_bins
),
scalar_selectors
(),
scalar_selectors
(),
boost
::
mpl
::
vector
<
dummy_weight
>
())
(
degree_selector
(
deg1
),
degree_selector
(
deg2
),
dummy_weight
());
(
any
(
degree_selector
(
deg1
)),
any
(
degree_selector
(
deg2
)),
any
(
dummy_weight
()));
return
boost
::
python
::
make_tuple
(
avg
,
dev
,
ret_bins
);
}
...
...
src/graph/correlations/graph_correlations_combined.cc
View file @
7a84d0f3
...
...
@@ -50,7 +50,7 @@ get_vertex_combined_correlation_histogram(GraphInterface& gi,
ret_bins
),
scalar_selectors
(),
scalar_selectors
(),
boost
::
mpl
::
vector
<
dummy_weight
>
())
(
degree_selector
(
deg1
),
degree_selector
(
deg2
),
(
any
(
degree_selector
(
deg1
)
)
,
any
(
degree_selector
(
deg2
)
)
,
boost
::
any
(
dummy_weight
()));
return
boost
::
python
::
make_tuple
(
hist
,
ret_bins
);
...
...
src/graph/graph.hh
View file @
7a84d0f3
...
...
@@ -48,8 +48,7 @@ namespace detail
{
// Generic graph_action functor. See graph_filtering.hh for details.
template
<
class
Action
,
class
GraphViews
,
class
Wrap
=
boost
::
mpl
::
false_
,
class
TR1
=
boost
::
mpl
::
vector
<
>,
class
TR2
=
boost
::
mpl
::
vector
<>
,
class
TR3
=
boost
::
mpl
::
vector
<>
,
class
TR4
=
boost
::
mpl
::
vector
<>
>
class
...
TRS
>
struct
graph_action
;
}
...
...
src/graph/graph_filtering.cc
View file @
7a84d0f3
...
...
@@ -16,7 +16,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include
"graph_filtering.hh"
#include
<
boost/python/type_id.hpp
>
#include
<
cxxabi.h
>
using
namespace
graph_tool
;
using
namespace
graph_tool
::
detail
;
...
...
@@ -31,6 +31,15 @@ bool graph_tool::graph_filtering_enabled()
#endif
}
string
name_demangle
(
string
name
)
{
int
status
=
0
;
char
*
realname
=
abi
::
__cxa_demangle
(
name
.
c_str
(),
0
,
0
,
&
status
);
string
ret
(
realname
);
free
(
realname
);
return
ret
;
}
// Whenever no implementation is called, the following exception is thrown
graph_tool
::
ActionNotFound
::
ActionNotFound
(
const
boost
::
any
&
graph_view
,
const
type_info
&
action
,
...
...
@@ -48,14 +57,12 @@ const char * graph_tool::ActionNotFound::what () const throw ()
"instructions at "
PACKAGE_BUGREPORT
". What follows is debug "
"information.
\n\n
"
;
error
+=
"Graph view: "
+
string
(
gcc_demangle
(
_graph_view
.
type
().
name
()))
+
"
\n\n
"
;
error
+=
"Action: "
+
string
(
gcc_demangle
(
_action
.
name
()))
+
"
\n\n
"
;
error
+=
"Graph view: "
+
name_demangle
(
_graph_view
.
type
().
name
())
+
"
\n\n
"
;
error
+=
"Action: "
+
name_demangle
(
_action
.
name
())
+
"
\n\n
"
;
for
(
size_t
i
=
0
;
i
<
_args
.
size
();
++
i
)
{
error
+=
"Arg "
+
lexical_cast
<
string
>
(
i
+
1
)
+
": "
+
string
(
gcc
_demangle
(
_args
[
i
]
->
name
())
)
+
"
\n\n
"
;
name
_demangle
(
_args
[
i
]
->
name
())
+
"
\n\n
"
;
}
return
error
.
c_str
();
}
...
...
src/graph/graph_filtering.hh
View file @
7a84d0f3
...
...
@@ -558,23 +558,16 @@ struct action_wrap
Type
&
uncheck
(
Type
&
a
,
DoWrap
)
const
{
return
a
;
}
void
operator
()()
const
{};
template
<
class
T1
>
void
operator
()(
T1
*
a1
)
const
{
_a
(
*
a1
);
}
template
<
class
T1
,
class
T2
>
void
operator
()(
T1
*
a1
,
T2
&
a2
)
const
{
_a
(
*
a1
,
uncheck
(
a2
,
Wrap
()));
}
template
<
class
T1
,
class
T2
,
class
T3
>
void
operator
()(
T1
*
a1
,
T2
&
a2
,
T3
&
a3
)
const
{
_a
(
*
a1
,
uncheck
(
a2
,
Wrap
()),
uncheck
(
a3
,
Wrap
()));
}
template
<
class
T1
,
class
T2
,
class
T3
,
class
T4
>
void
operator
()(
T1
*
a1
,
T2
&
a2
,
T3
&
a3
,
T4
&
a4
)
const
{
_a
(
*
a1
,
uncheck
(
a2
,
Wrap
()),
uncheck
(
a3
,
Wrap
()),
uncheck
(
a4
,
Wrap
()));
}
template
<
class
T1
,
class
T2
,
class
T3
,
class
T4
,
class
T5
>
void
operator
()(
T1
*
a1
,
T2
&
a2
,
T3
&
a3
,
T4
&
a4
,
T5
&
a5
)
const
{
_a
(
*
a1
,
uncheck
(
a2
,
Wrap
()),
uncheck
(
a3
,
Wrap
()),
uncheck
(
a4
,
Wrap
()),
uncheck
(
a5
,
Wrap
()));
}
template
<
class
T1
,
class
...
Ts
>
void
operator
()(
T1
*
a1
,
Ts
&&
...
as
)
const
{
_a
(
*
a1
,
uncheck
(
std
::
forward
<
Ts
>
(
as
),
Wrap
())...);
}
Action
_a
;
reference_wrapper
<
GraphInterface
>
_g
;
...
...
@@ -583,8 +576,7 @@ struct action_wrap
// this functor encapsulates another functor Action, which takes a pointer to a
// graph view as first argument
template
<
class
Action
,
class
GraphViews
,
class
Wrap
,
class
TR1
,
class
TR2
,
class
TR3
,
class
TR4
>
template
<
class
Action
,
class
GraphViews
,
class
Wrap
,
class
...
TRS
>
struct
graph_action
{
struct
graph_view_pointers
:
...
...
@@ -594,79 +586,17 @@ struct graph_action
:
_g
(
g
),
_a
(
a
,
g
,
num_vertices
(
*
g
.
_mg
),
max
(
g
.
_mg
->
get_last_index
(),
size_t
(
1
)))
{}
void
operator
()()
const
{
bool
found
=
false
;
boost
::
any
gview
=
_g
.
GetGraphView
();
boost
::
mpl
::
for_each
<
graph_view_pointers
>
(
boost
::
mpl
::
select_types
(
_a
,
found
,
gview
));
if
(
!
found
)
{
throw
ActionNotFound
(
gview
,
typeid
(
Action
),
vector
<
const
std
::
type_info
*>
());
}
}
void
operator
()(
boost
::
any
a1
)
const
template
<
class
...
Args
>
void
operator
()(
Args
&&
...
args
)
const
{
bool
found
=
false
;
boost
::
any
gview
=
_g
.
GetGraphView
();
boost
::
mpl
::
nested_for_each
<
graph_view_pointers
,
TR
1
>
()
(
boost
::
mpl
::
select_types
(
_a
,
found
,
gview
,
a1
));
boost
::
mpl
::
nested_for_each
<
graph_view_pointers
,
TR
S
...
>
(
boost
::
mpl
::
select_types
(
_a
,
found
,
gview
,
std
::
forward
<
Args
>
(
args
)...
));
if
(
!
found
)
{
vector
<
const
std
::
type_info
*>
args
;
args
.
push_back
(
&
a1
.
type
());
throw
ActionNotFound
(
gview
,
typeid
(
Action
),
args
);
}
}
void
operator
()(
boost
::
any
a1
,
boost
::
any
a2
)
const
{
bool
found
=
false
;
boost
::
any
gview
=
_g
.
GetGraphView
();
boost
::
mpl
::
nested_for_each
<
graph_view_pointers
,
TR1
,
TR2
>
()
(
boost
::
mpl
::
select_types
(
_a
,
found
,
gview
,
a1
,
a2
));
if
(
!
found
)
{
vector
<
const
std
::
type_info
*>
args
;
args
.
push_back
(
&
a1
.
type
());
args
.
push_back
(
&
a2
.
type
());
throw
ActionNotFound
(
gview
,
typeid
(
Action
),
args
);
}
}
void
operator
()(
boost
::
any
a1
,
boost
::
any
a2
,
boost
::
any
a3
)
const
{
bool
found
=
false
;
boost
::
any
gview
=
_g
.
GetGraphView
();
boost
::
mpl
::
nested_for_each
<
graph_view_pointers
,
TR1
,
TR2
,
TR3
>
()
(
boost
::
mpl
::
select_types
(
_a
,
found
,
gview
,
a1
,
a2
,
a3
));
if
(
!
found
)
{
vector
<
const
std
::
type_info
*>
args
;
args
.
push_back
(
&
a1
.
type
());
args
.
push_back
(
&
a2
.
type
());
args
.
push_back
(
&
a3
.
type
());
throw
ActionNotFound
(
gview
,
typeid
(
Action
),
args
);
}
}
void
operator
()(
boost
::
any
a1
,
boost
::
any
a2
,
boost
::
any
a3
,
boost
::
any
a4
)
const
{
bool
found
=
false
;
boost
::
any
gview
=
_g
.
GetGraphView
();
boost
::
mpl
::
nested_for_each
<
graph_view_pointers
,
TR1
,
TR2
,
TR3
,
TR4
>
()
(
boost
::
mpl
::
select_types
(
_a
,
found
,
gview
,
a1
,
a2
,
a3
,
a4
));
if
(
!
found
)
{
vector
<
const
std
::
type_info
*>
args
;
args
.
push_back
(
&
a1
.
type
());
args
.
push_back
(
&
a2
.
type
());
args
.
push_back
(
&
a3
.
type
());
args
.
push_back
(
&
a4
.
type
());
throw
ActionNotFound
(
gview
,
typeid
(
Action
),
args
);
vector
<
const
std
::
type_info
*>
args_t
=
{(
&
(
args
).
type
())...};
throw
ActionNotFound
(
gview
,
typeid
(
Action
),
args_t
);
}
}
...
...
@@ -680,39 +610,11 @@ struct graph_action
template
<
class
GraphViews
=
detail
::
all_graph_views
,
class
Wrap
=
boost
::
mpl
::
false_
>
struct
run_action
{
template
<
class
Action
>
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
>
operator
()(
GraphInterface
&
g
,
Action
a
)
{
return
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
>
(
g
,
a
);
}
template
<
class
Action
,
class
TR1
>
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
,
TR1
>
operator
()(
GraphInterface
&
g
,
Action
a
,
TR1
)
{
return
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
,
TR1
>
(
g
,
a
);
}
template
<
class
Action
,
class
TR1
,
class
TR2
>
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
,
TR1
,
TR2
>
operator
()(
GraphInterface
&
g
,
Action
a
,
TR1
,
TR2
)
{
return
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
,
TR1
,
TR2
>
(
g
,
a
);
}
template
<
class
Action
,
class
TR1
,
class
TR2
,
class
TR3
>
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
,
TR1
,
TR2
,
TR3
>
operator
()(
GraphInterface
&
g
,
Action
a
,
TR1
,
TR2
,
TR3
)
{
return
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
,
TR1
,
TR2
,
TR3
>
(
g
,
a
);
}
template
<
class
Action
,
class
TR1
,
class
TR2
,
class
TR3
,
class
TR4
>
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
,
TR1
,
TR2
,
TR3
,
TR4
>
operator
()(
GraphInterface
&
g
,
Action
a
,
TR1
,
TR2
,
TR3
,
TR4
)
template
<
class
Action
,
class
...
TRS
>
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
,
TRS
...
>
operator
()(
GraphInterface
&
g
,
Action
&&
a
,
TRS
...)
{
return
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
,
TR
1
,
TR2
,
TR3
,
TR4
>
(
g
,
a
);
return
detail
::
graph_action
<
Action
,
GraphViews
,
Wrap
,
TR
S
...
>
(
g
,
std
::
forward
<
Action
>
(
a
)
);
}
};
...
...
src/graph/mpl_nested_loop.hh
View file @
7a84d0f3
...
...
@@ -51,164 +51,68 @@ namespace mpl
// The code above will run foo::operator(T1, T2, T3) for all combinations given
// by r1, r2 and r3. This provides a more general compile-time to run-time
// meta-programming than the more simple mpl::for_each().
//
// Implementation notes: This supports up to 5 nested type ranges. In principle
// this could be generalized, and a lot of the boiler plate code in the
// implementation could be eliminated, by making more thorough use of MPL's
// meta-functions. My attempts to do this, however, tried to make use of
// lambda's bind function, which requires the arity of the function being bound
// to be known in advance. I tried to implement a bind_last() function, which
// always binds the last argument of a given functor, independently of its exact
// arity, but it made use of the typeof operator a lot, and at a given point
// caused GCC (4.2.2) to ICE... Thus, I decided to write the inner loops by
// hand, and wait before GCC implements the auto and typedecl functionality of
// c++0x, making the life of C++ template meta-programmers less horrible.
//
// In any case, "five nested levels should be enough for everybody".
template
<
class
TR1
,
class
TR2
,
class
TR3
,
class
TR4
,
class
TR5
>
struct
nested_for_ea
ch
template
<
class
Action
,
class
...
Args
>
struct
dispat
ch
{
template
<
class
Action
>
void
operator
()(
Action
a
)
const
{
for_each
<
TR1
>
(
inner_loop1
<
Action
>
(
a
));
}
template
<
class
Action
>
struct
inner_loop1
{
inner_loop1
(
Action
a
)
:
_a
(
a
)
{}
template
<
class
T1
>
void
operator
()(
T1
)
const
{
typedef
typename
mpl
::
if_
<
mpl
::
empty
<
TR3
>
,
TR2
,
mpl
::
vector
<>
>::
type
eval_range
;
if
(
mpl
::
empty
<
TR3
>::
type
::
value
)
for_each
<
eval_range
>
(
eval_action2
<
Action
,
T1
>
(
_a
));
else
for_each
<
TR2
>
(
inner_loop2
<
Action
,
T1
>
(
_a
));
}
Action
_a
;
};
template
<
class
Action
,
class
T1
>
struct
inner_loop2
{
inner_loop2
(
Action
a
)
:
_a
(
a
)
{}
template
<
class
T2
>
void
operator
()(
T2
)
const
{
typedef
typename
mpl
::
if_
<
mpl
::
empty
<
TR4
>
,
TR3
,
mpl
::
vector
<>
>::
type
eval_range
;
if
(
mpl
::
empty
<
TR4
>::
type
::
value
)
for_each
<
eval_range
>
(
eval_action3
<
Action
,
T1
,
T2
>
(
_a
));
else
for_each
<
TR3
>
(
inner_loop3
<
Action
,
T1
,
T2
>
(
_a
));
}
Action
_a
;
};
dispatch
(
Action
a
)
:
_a
(
a
)
{}
template
<
class
Action
,
class
T1
,
class
T2
>
struct
inner_loop3
template
<
class
T
>
dispatch
<
Action
,
Args
...,
T
>
join
()
const
{
inner_loop3
(
Action
a
)
:
_a
(
a
)
{}
template
<
class
T3
>
void
operator
()(
T3
)
const
{
typedef
typename
mpl
::
if_
<
mpl
::
empty
<
TR5
>
,
TR4
,
mpl
::
vector
<>
>::
type
eval_range
;
if
(
mpl
::
empty
<
TR5
>::
type
::
value
)
for_each
<
eval_range
>
(
eval_action4
<
Action
,
T1
,
T2
,
T3
>
(
_a
));
else
for_each
<
TR4
>
(
inner_loop4
<
Action
,
T1
,
T2
,
T3
>
(
_a
));
}
Action
_a
;
};
return
dispatch
<
Action
,
Args
...,
T
>
(
_a
);
}
template
<
class
Action
,
class
T1
,
class
T2
,
class
T
3
>
struct
inner_loop4
template
<
class
T
>
void
operator
()(
T
)
const
{
inner_loop4
(
Action
a
)
:
_a
(
a
)
{}
template
<
class
T4
>
void
operator
()(
T4
)
const
{
for_each
<
TR5
>
(
eval_action5
<
Action
,
T1
,
T2
,
T3
,
T4
>
(
_a
));
}
Action
_a
;
};
_a
(
Args
()...,
T
());
}
template
<
class
Action
,
class
T1
>
struct
eval_action2
void
operator
()()
const
{
eval_action2
(
Action
a
)
:
_a
(
a
)
{}
template
<
class
T2
>
void
operator
()(
T2
)
const
{
_a
(
T1
(),
T2
());
}
Action
_a
;
};
_a
(
Args
()...);
}
template
<
class
Action
,
class
T1
,
class
T2
>
struct
eval_action3
{
eval_action3
(
Action
a
)
:
_a
(
a
)
{}
Action
_a
;
};
template
<
class
T3
>
void
operator
()(
T3
)
const
{
_a
(
T1
(),
T2
(),
T3
());
}
template
<
class
TR1
,
class
...
TRS
,
class
Action
>
void
nested_for_each_imp
(
Action
a
);
Action
_a
;
};
template
<
class
Action
,
class
...
TRS
>
struct
inner_loop
{
inner_loop
(
Action
a
)
:
_a
(
a
)
{}
template
<
class
Action
,
class
T1
,
class
T2
,
class
T
3
>
struct
eval_action4
template
<
class
T
>
void
operator
()(
T
)
const
{
eval_action4
(
Action
a
)
:
_a
(
a
)
{}
template
<
class
T4
>
void
operator
()(
T4
)
const
{
_a
(
T1
(),
T2
(),
T3
(),
T4
());
}
nested_for_each_imp
<
TRS
...
>
(
_a
.
join
<
T
>
());
}
Action
_a
;
};
Action
_a
;
};
template
<
class
Action
,
class
T1
,
class
T2
,
class
T3
,
class
T4
>
struct
eval_action5
{
eval_action5
(
Action
a
)
:
_a
(
a
)
{}
template
<
class
TR1
,
class
...
TRS
,
class
Action
>
void
nested_for_each_imp
(
Action
a
)
{
for_each
<
TR1
>
(
inner_loop
<
Action
,
TRS
...
>
(
a
));
}
template
<
class
T5
>
void
operator
()(
T5
)
const
{
_a
(
T1
(),
T2
(),
T3
(),
T4
(),
T5
()
);
}
template
<
class
Action
>
void
nested_for_each_imp
(
Action
a
)
{
a
(
);
}
Action
_a
;
};
};
template
<
class
...
TRS
,
class
Action
>
void
nested_for_each
(
Action
a
)
{
auto
b
=
dispatch
<
Action
>
(
a
);
nested_for_each_imp
<
TRS
...
>
(
b
);
}
template
<
class
TR1
,
class
TR2
,
class
TR3
=
mpl
::
vector
<
>,
class
TR4
=
mpl
::
vector
<>
,
class
TR5
=
mpl
::
vector
<>
>
struct
nested_for_each
;
// The functor below wraps another functor Action, but only calls it for the
// correct argument types, determined at runtime. Together with
...
...
@@ -237,93 +141,49 @@ struct nested_for_each;
template
<
class
Action
>
struct
selected_types
;
// forward decl.
template
<
class
Action
>
template
<
class
Action
,
class
...
Args
>
selected_types
<
Action
>
select_types
(
Action
a
,
bool
&
found
,
any
a1
=
any
(),
any
a2
=
any
(),
any
a3
=
any
(),
any
a4
=
any
(),
any
a5
=
any
())
select_types
(
Action
a
,
bool
&
found
,
Args
...
args
)
{
return
selected_types
<
Action
>
(
a
,
found
,
a
1
,
a2
,
a3
,
a4
,
a5
);
return
selected_types
<
Action
>
(
a
,
found
,
a
rgs
...
);
}
template
<
class
Action
>
struct
selected_types
{
selected_types
(
Action
a
,
bool
&
found
,
any
a1
,
any
a2
,
any
a3
,
any
a4
,
any
a5
)
:
_a
(
a
),
_found
(
found
),
_a1
(
a1
),
_a2
(
a2
),
_a3
(
a3
),
_a4
(
a4
),
_a5
(
a5
)
{}
template
<
class
T1
>
void
operator
()(
T1
)
const
template
<
class
...
Args
>
selected_types
(
Action
a
,
bool
&
found
,
Args
&&
...
args
)
:
_a
(
a
),
_found
(
found
)
{
T1
*
a1
=
const_cast
<
T1
*>
(
any_cast
<
T1
>
(
&
_a1
));
if
(
a1
!=
0
)
{
_a
(
*
a1
);
_found
=
true
;
}
_args
=
{
args
...};
}
template
<
class
T1
,
class
T2
>
void
operator
()(
T1
,
T2
)
const
{
T1
*
a1
=
const_cast
<
T1
*>
(
any_cast
<
T1
>
(
&
_a1
));
T2
*
a2
=
const_cast
<
T2
*>
(
any_cast
<
T2
>
(
&
_a2
));
if
(
a1
!=
0
&&
a2
!=
0
)
{
_a
(
*
a1
,
*
a2
);
_found
=
true
;
}
}
template
<
class
T1
,
class
T
2
,
class
T
3
>
void
operator
()(
T1
,
T2
,
T3
)
const
template
<
class
...
Args
,
class
T
,
class
...
T
s
>
void
dispatch
(
unsigned
int
i
,
std
::
tuple
<
T
,
Ts
...
>
,
Args
&&
...
args
)
const
{
T1
*
a1
=
const_cast
<
T1
*>
(
any_cast
<
T1
>
(
&
_a1
));
T2
*
a2
=
const_cast
<
T2
*>
(
any_cast
<
T2
>
(
&
_a2
));
T3
*
a3
=
const_cast
<
T3
*>
(
any_cast
<
T3
>
(
&
_a3
));
if
(
a1
!=
0
&&
a2
!=
0
&&
a3
!=
0
)
{
_a
(
*
a1
,
*
a2
,
*
a3
);
_found
=
true
;
}
assert
(
i
<
_args
.
size
());
T
*
a
=
const_cast
<
T
*>
(
any_cast
<
T
>
(
&
_args
[
i
]));
if
(
a
!=
0
)
dispatch
(
i
+
1
,
std
::
tuple
<
Ts
...
>
(),
std
::
forward
<
Args
>
(
args
)...,
*
a
);
}
template
<
class
T1
,
class
T2
,
class
T3
,
class
T4
>
void
operator
()(
T1
,
T2
,
T3
,
T4
)
const
template
<
class
...
Args
>
void
dispatch
(
unsigned
int
i
,
std
::
tuple
<>
,
Args
&&
...
args
)
const
{
T1
*
a1
=
const_cast
<
T1
*>
(
any_cast
<
T1
>
(
&
_a1
));
T2
*
a2
=
const_cast
<
T2
*>
(
any_cast
<
T2
>
(
&
_a2
));
T3
*
a3
=
const_cast
<
T3
*>
(
any_cast
<
T3
>
(
&
_a3
));
T4
*
a4
=
const_cast
<
T4
*>
(
any_cast
<
T4
>
(
&
_a4
));
if
(
a1
!=
0
&&
a2
!=
0
&&
a3
!=
0
&&
a4
!=
0
)
{
_a
(
*
a1
,
*
a2
,
*
a3
,
*
a4
);
_found
=
true
;
}
_a
(
std
::
forward
<
Args
>
(
args
)...);
_found
=
true
;
}
template
<
class
T1
,
class
T2
,
class
T3
,
class
T4
,
class
T5
>
void
operator
()(
T
1
,
T2
,
T3
,
T4
,
T5
)
const
template
<
class
...
Ts
>
void
operator
()(
T
s
&&
...
ts
)
const
{
T1
*
a1
=
const_cast
<
T1
*>
(
any_cast
<
T1
>
(
&
_a1
));
T2
*
a2
=
const_cast
<
T2
*>
(
any_cast
<
T2
>
(
&
_a2
));
T3
*
a3
=
const_cast
<
T3
*>
(
any_cast
<
T3
>
(
&
_a3
));
T4
*
a4
=
const_cast
<
T4
*>
(
any_cast
<
T4
>
(
&
_a4
));
T5
*
a5
=
const_cast
<
T5
*>
(
any_cast
<
T5
>
(
&
_a5
));
if
(
a1
!=
0
&&
a2
!=
0
&&
a3
!=
0
&&
a4
!=
0
&&
a5
!=
0
)
{
_a
(
*
a1
,
*
a2
,
*
a3
,
*
a4
,
*
a5
);
_found
=
true
;
}
dispatch
(
0
,
std
::
tuple
<
Ts
...
>
());
}
Action
_a
;
bool
&
_found
;
any
_a
1
,
_a2
,
_a3
,
_a4
,
_a5
;
std
::
vector
<
any
>
_a
rgs
;
};
}
// mpl namespace
...
...
Write
Preview
Supports
Markdown
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