Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
332f9eee
Commit
332f9eee
authored
Apr 13, 2012
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
new guard and pattern matching implementation
parent
d3d55a4c
Changes
42
Show whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
1606 additions
and
1618 deletions
+1606
-1618
Makefile.am
Makefile.am
+2
-2
benchmarks/actor_creation.cpp
benchmarks/actor_creation.cpp
+6
-6
cppa.files
cppa.files
+2
-2
cppa/actor.hpp
cppa/actor.hpp
+6
-3
cppa/any_tuple.hpp
cppa/any_tuple.hpp
+12
-4
cppa/behavior.hpp
cppa/behavior.hpp
+72
-27
cppa/cppa.hpp
cppa/cppa.hpp
+26
-12
cppa/detail/default_uniform_type_info_impl.hpp
cppa/detail/default_uniform_type_info_impl.hpp
+9
-9
cppa/detail/projection.hpp
cppa/detail/projection.hpp
+5
-0
cppa/detail/pseudo_tuple.hpp
cppa/detail/pseudo_tuple.hpp
+50
-18
cppa/detail/receive_loop_helper.hpp
cppa/detail/receive_loop_helper.hpp
+11
-24
cppa/detail/tdata.hpp
cppa/detail/tdata.hpp
+13
-10
cppa/event_based_actor_base.hpp
cppa/event_based_actor_base.hpp
+5
-11
cppa/fsm_actor.hpp
cppa/fsm_actor.hpp
+0
-1
cppa/get.hpp
cppa/get.hpp
+14
-3
cppa/guard_expr.hpp
cppa/guard_expr.hpp
+1
-2
cppa/intrusive_ptr.hpp
cppa/intrusive_ptr.hpp
+0
-1
cppa/match.hpp
cppa/match.hpp
+33
-17
cppa/match_expr.hpp
cppa/match_expr.hpp
+1007
-0
cppa/on.hpp
cppa/on.hpp
+172
-140
cppa/partial_function.hpp
cppa/partial_function.hpp
+28
-33
cppa/primitive_variant.hpp
cppa/primitive_variant.hpp
+8
-10
cppa/receive.hpp
cppa/receive.hpp
+8
-18
cppa/util/apply_tuple.hpp
cppa/util/apply_tuple.hpp
+2
-2
cppa/util/disable_if.hpp
cppa/util/disable_if.hpp
+0
-57
cppa/util/is_forward_iterator.hpp
cppa/util/is_forward_iterator.hpp
+5
-5
cppa/util/is_iterable.hpp
cppa/util/is_iterable.hpp
+2
-2
cppa/util/type_list.hpp
cppa/util/type_list.hpp
+17
-2
examples/math_actor_example.cpp
examples/math_actor_example.cpp
+1
-1
src/binary_deserializer.cpp
src/binary_deserializer.cpp
+3
-4
src/binary_serializer.cpp
src/binary_serializer.cpp
+3
-4
src/partial_function.cpp
src/partial_function.cpp
+2
-91
src/primitive_variant.cpp
src/primitive_variant.cpp
+2
-2
src/scheduler.cpp
src/scheduler.cpp
+9
-0
src/uniform_type_info.cpp
src/uniform_type_info.cpp
+3
-6
unit_testing/main.cpp
unit_testing/main.cpp
+2
-2
unit_testing/test.hpp
unit_testing/test.hpp
+8
-5
unit_testing/test__match.cpp
unit_testing/test__match.cpp
+9
-6
unit_testing/test__pattern.cpp
unit_testing/test__pattern.cpp
+0
-2
unit_testing/test__serialization.cpp
unit_testing/test__serialization.cpp
+0
-2
unit_testing/test__spawn.cpp
unit_testing/test__spawn.cpp
+5
-0
unit_testing/test__tuple.cpp
unit_testing/test__tuple.cpp
+43
-1072
No files found.
Makefile.am
View file @
332f9eee
...
...
@@ -122,6 +122,7 @@ nobase_library_include_HEADERS = \
cppa/detail/post_office_msg.hpp
\
cppa/detail/primitive_member.hpp
\
cppa/detail/projection.hpp
\
cppa/detail/pseudo_tuple.hpp
\
cppa/detail/ptype_to_type.hpp
\
cppa/detail/receive_loop_helper.hpp
\
cppa/detail/ref_counted_impl.hpp
\
...
...
@@ -159,6 +160,7 @@ nobase_library_include_HEADERS = \
cppa/intrusive_ptr.hpp
\
cppa/local_actor.hpp
\
cppa/match.hpp
\
cppa/match_expr.hpp
\
cppa/object.hpp
\
cppa/on.hpp
\
cppa/option.hpp
\
...
...
@@ -190,11 +192,9 @@ nobase_library_include_HEADERS = \
cppa/util/compare_tuples.hpp
\
cppa/util/conjunction.hpp
\
cppa/util/deduce_ref_type.hpp
\
cppa/util/disable_if.hpp
\
cppa/util/disjunction.hpp
\
cppa/util/duration.hpp
\
cppa/util/element_at.hpp
\
cppa/util/enable_if.hpp
\
cppa/util/fiber.hpp
\
cppa/util/fixed_vector.hpp
\
cppa/util/if_else.hpp
\
...
...
benchmarks/actor_creation.cpp
View file @
332f9eee
...
...
@@ -57,18 +57,18 @@ struct testee : fsm_actor<testee>
send
(
parent
,
atom
(
"result"
),
(
uint32_t
)
1
);
become_void
();
},
on
(
atom
(
"spread"
),
arg_match
)
>>
[
=
](
int
x
)
on
<
atom
(
"spread"
),
int
>
(
)
>>
[
=
](
int
x
)
{
any_tuple
msg
=
make_cow_tuple
(
atom
(
"spread"
),
x
-
1
);
spawn
(
new
testee
(
this
))
<<
msg
;
spawn
(
new
testee
(
this
))
<<
msg
;
become
(
on
(
atom
(
"result"
),
arg_match
)
>>
[
=
](
uint32_t
r1
)
on
<
atom
(
"result"
),
uint32_t
>
(
)
>>
[
=
](
uint32_t
r1
)
{
become
(
on
(
atom
(
"result"
),
arg_match
)
>>
[
=
](
uint32_t
r2
)
on
<
atom
(
"result"
),
uint32_t
>
(
)
>>
[
=
](
uint32_t
r2
)
{
send
(
parent
,
atom
(
"result"
),
r1
+
r2
);
become_void
();
...
...
@@ -89,18 +89,18 @@ void stacked_testee(actor_ptr parent)
{
send
(
parent
,
atom
(
"result"
),
(
uint32_t
)
1
);
},
on
(
atom
(
"spread"
),
arg_match
)
>>
[
&
](
int
x
)
on
<
atom
(
"spread"
),
int
>
(
)
>>
[
&
](
int
x
)
{
any_tuple
msg
=
make_cow_tuple
(
atom
(
"spread"
),
x
-
1
);
spawn
(
stacked_testee
,
self
)
<<
msg
;
spawn
(
stacked_testee
,
self
)
<<
msg
;
receive
(
on
(
atom
(
"result"
),
arg_match
)
>>
[
&
](
uint32_t
v1
)
on
<
atom
(
"result"
),
uint32_t
>
(
)
>>
[
&
](
uint32_t
v1
)
{
receive
(
on
(
atom
(
"result"
),
arg_match
)
>>
[
&
](
uint32_t
v2
)
on
<
atom
(
"result"
),
uint32_t
>
(
)
>>
[
&
](
uint32_t
v2
)
{
send
(
parent
,
atom
(
"result"
),
v1
+
v2
);
}
...
...
cppa.files
View file @
332f9eee
...
...
@@ -30,7 +30,6 @@ cppa/on.hpp
unit_testing/test__serialization.cpp
cppa/serializer.hpp
cppa/deserializer.hpp
cppa/util/enable_if.hpp
cppa/object.hpp
cppa/detail/object_impl.hpp
cppa/detail/swap_bytes.hpp
...
...
@@ -76,7 +75,6 @@ src/to_uniform_name.cpp
cppa/detail/default_uniform_type_info_impl.hpp
src/object.cpp
cppa/util/comparable.hpp
cppa/util/disable_if.hpp
cppa/primitive_variant.hpp
cppa/primitive_type.hpp
cppa/util/pt_token.hpp
...
...
@@ -268,3 +266,5 @@ cppa/util/deduce_ref_type.hpp
cppa/detail/projection.hpp
cppa/detail/value_guard.hpp
cppa/detail/tuple_iterator.hpp
cppa/match_expr.hpp
cppa/detail/pseudo_tuple.hpp
cppa/actor.hpp
View file @
332f9eee
...
...
@@ -41,7 +41,6 @@
#include "cppa/process_information.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/enable_if.hpp"
namespace
cppa
{
...
...
@@ -94,7 +93,9 @@ class actor : public channel
template
<
typename
T
>
bool
attach
(
std
::
unique_ptr
<
T
>&&
ptr
,
typename
util
::
enable_if
<
std
::
is_base_of
<
attachable
,
T
>>::
type
*
=
0
);
typename
std
::
enable_if
<
std
::
is_base_of
<
attachable
,
T
>::
value
>::
type
*
=
0
);
/**
* @brief Forces this actor to subscribe to the group @p what.
...
...
@@ -238,7 +239,9 @@ inline bool actor::is_proxy() const
template
<
typename
T
>
bool
actor
::
attach
(
std
::
unique_ptr
<
T
>&&
ptr
,
typename
util
::
enable_if
<
std
::
is_base_of
<
attachable
,
T
>>::
type
*
)
typename
std
::
enable_if
<
std
::
is_base_of
<
attachable
,
T
>::
value
>::
type
*
)
{
return
attach
(
static_cast
<
attachable
*>
(
ptr
.
release
()));
}
...
...
cppa/any_tuple.hpp
View file @
332f9eee
...
...
@@ -31,13 +31,13 @@
#ifndef ANY_TUPLE_HPP
#define ANY_TUPLE_HPP
#include <type_traits>
#include "cppa/cow_tuple.hpp"
#include "cppa/config.hpp"
#include "cppa/cow_ptr.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/is_iterable.hpp"
#include "cppa/detail/tuple_view.hpp"
...
...
@@ -162,7 +162,11 @@ class any_tuple
template
<
typename
T
>
static
inline
any_tuple
view
(
T
&&
value
,
typename
util
::
enable_if
<
util
::
is_iterable
<
typename
util
::
rm_ref
<
T
>::
type
>
>::
type
*
=
0
)
typename
std
::
enable_if
<
util
::
is_iterable
<
typename
util
::
rm_ref
<
T
>::
type
>::
value
>::
type
*
=
0
)
{
static
constexpr
bool
can_optimize
=
std
::
is_reference
<
T
>::
value
&&
!
std
::
is_const
<
T
>::
value
;
...
...
@@ -172,7 +176,11 @@ class any_tuple
template
<
typename
T
>
static
inline
any_tuple
view
(
T
&&
value
,
typename
util
::
disable_if
<
util
::
is_iterable
<
typename
util
::
rm_ref
<
T
>::
type
>
>::
type
*
=
0
)
typename
std
::
enable_if
<
util
::
is_iterable
<
typename
util
::
rm_ref
<
T
>::
type
>::
value
==
false
>::
type
*
=
0
)
{
typedef
typename
util
::
rm_ref
<
T
>::
type
vtype
;
typedef
typename
detail
::
implicit_conversions
<
vtype
>::
type
converted
;
...
...
cppa/behavior.hpp
View file @
332f9eee
...
...
@@ -34,12 +34,15 @@
#include <functional>
#include <type_traits>
#include "cppa/match_expr.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/
partial_f
unction.hpp"
#include "cppa/
util/disj
unction.hpp"
namespace
cppa
{
...
...
@@ -58,18 +61,27 @@ class behavior
behavior
()
=
default
;
behavior
(
behavior
&&
)
=
default
;
behavior
&
operator
=
(
behavior
&&
)
=
default
;
inline
behavior
(
partial_function
&&
fun
)
:
m_fun
(
std
::
move
(
fun
))
{
}
template
<
typename
...
Cases
>
behavior
(
match_expr
<
Cases
...
>
const
&
me
)
:
m_fun
(
me
)
{
}
inline
behavior
(
util
::
duration
tout
,
std
::
function
<
void
()
>&&
handler
)
:
m_timeout
(
tout
),
m_timeout_handler
(
std
::
move
(
handler
))
{
}
behavior
&
operator
=
(
behavior
&&
)
=
default
;
//behavior& operator=(partial_function&& pfun)
//{
// m_fun = std::move(pfun);
// return *this;
//}
inline
void
handle_timeout
()
const
{
m_timeout_handler
();
...
...
@@ -80,31 +92,11 @@ class behavior
return
m_timeout
;
}
inline
void
operator
()(
any_tuple
const
&
value
)
{
m_fun
(
value
);
}
inline
partial_function
&
get_partial_function
()
{
return
m_fun
;
}
inline
behavior
&
splice
(
behavior
&&
what
)
{
m_fun
.
splice
(
std
::
move
(
what
.
get_partial_function
()));
m_timeout
=
what
.
m_timeout
;
m_timeout_handler
=
std
::
move
(
what
.
m_timeout_handler
);
return
*
this
;
}
template
<
class
...
Args
>
inline
behavior
&
splice
(
partial_function
&&
arg0
,
Args
&&
...
args
)
{
m_fun
.
splice
(
std
::
move
(
arg0
));
return
splice
(
std
::
forward
<
Args
>
(
args
)...);
}
private:
// terminates recursion
...
...
@@ -116,16 +108,69 @@ class behavior
};
template
<
typename
...
Lhs
>
behavior
operator
,(
match_expr
<
Lhs
...
>
const
&
lhs
,
behavior
&&
rhs
)
{
rhs
.
get_partial_function
()
=
lhs
;
return
std
::
move
(
rhs
);
}
template
<
typename
Arg0
>
behavior
bhvr_collapse
(
Arg0
&&
arg
)
{
return
{
std
::
forward
<
Arg0
>
(
arg
)};
}
template
<
typename
Arg0
,
typename
Arg1
,
typename
...
Args
>
behavior
bhvr_collapse
(
Arg0
&&
arg0
,
Arg1
&&
arg1
,
Args
&&
...
args
)
{
return
bhvr_collapse
((
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Arg1
>
(
arg1
)),
std
::
forward
<
Args
>
(
args
)...);
}
template
<
typename
...
Args
>
typename
std
::
enable_if
<
util
::
disjunction
<
std
::
is_same
<
behavior
,
Args
>
...
>::
value
,
behavior
>::
type
match_expr_concat
(
Args
&&
...
args
)
{
return
bhvr_collapse
(
std
::
forward
<
Args
>
(
args
)...);
}
template
<
typename
...
Args
>
typename
std
::
enable_if
<
util
::
disjunction
<
std
::
is_same
<
behavior
,
typename
util
::
rm_ref
<
Args
>::
type
>
...
>::
value
==
false
,
partial_function
>::
type
match_expr_concat
(
Args
&&
...
args
)
{
return
mexpr_concat_convert
(
std
::
forward
<
Args
>
(
args
)...);
}
inline
partial_function
match_expr_concat
(
partial_function
&&
pfun
)
{
return
std
::
move
(
pfun
);
}
inline
behavior
match_expr_concat
(
behavior
&&
bhvr
)
{
return
std
::
move
(
bhvr
);
}
namespace
detail
{
template
<
typename
...
Ts
>
struct
select_bhvr
{
static
constexpr
bool
timed
=
util
::
tl_exists
<
util
::
type_list
<
Ts
...
>
,
util
::
tbind
<
std
::
is_same
,
behavior
>::
type
>::
value
;
util
::
disjunction
<
std
::
is_same
<
behavior
,
Ts
>
...
>::
value
;
typedef
typename
util
::
if_else_c
<
timed
,
behavior
,
util
::
wrapped
<
partial_function
>
>::
type
...
...
cppa/cppa.hpp
View file @
332f9eee
...
...
@@ -55,8 +55,6 @@
#include "cppa/event_based_actor.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/detail/actor_count.hpp"
#include "cppa/detail/get_behavior.hpp"
...
...
@@ -512,9 +510,11 @@ inline actor_ptr spawn(abstract_event_based_actor* what)
template
<
scheduling_hint
Hint
,
typename
F
,
typename
...
Args
>
auto
//actor_ptr
spawn
(
F
&&
what
,
Args
const
&
...
args
)
->
typename
util
::
disable_if_c
<
std
::
is_convertible
<
typename
util
::
rm_ref
<
F
>::
type
,
scheduled_actor
*>::
value
||
std
::
is_convertible
<
typename
util
::
rm_ref
<
F
>::
type
,
event_based_actor
*>::
value
,
actor_ptr
>::
type
->
typename
std
::
enable_if
<
!
std
::
is_convertible
<
typename
util
::
rm_ref
<
F
>::
type
,
scheduled_actor
*>::
value
&&
!
std
::
is_convertible
<
typename
util
::
rm_ref
<
F
>::
type
,
event_based_actor
*>::
value
,
actor_ptr
>::
type
{
typedef
typename
util
::
rm_ref
<
F
>::
type
ftype
;
std
::
integral_constant
<
bool
,
std
::
is_function
<
ftype
>::
value
>
is_fun
;
...
...
@@ -529,9 +529,11 @@ spawn(F&& what, Args const&... args)
template
<
typename
F
,
typename
...
Args
>
auto
// actor_ptr
spawn
(
F
&&
what
,
Args
const
&
...
args
)
->
typename
util
::
disable_if_c
<
std
::
is_convertible
<
typename
util
::
rm_ref
<
F
>::
type
,
scheduled_actor
*>::
value
||
std
::
is_convertible
<
typename
util
::
rm_ref
<
F
>::
type
,
event_based_actor
*>::
value
,
actor_ptr
>::
type
->
typename
std
::
enable_if
<
!
std
::
is_convertible
<
typename
util
::
rm_ref
<
F
>::
type
,
scheduled_actor
*>::
value
&&
!
std
::
is_convertible
<
typename
util
::
rm_ref
<
F
>::
type
,
event_based_actor
*>::
value
,
actor_ptr
>::
type
{
return
spawn
<
scheduled
>
(
std
::
forward
<
F
>
(
what
),
args
...);
}
...
...
@@ -590,7 +592,10 @@ inline void send(self_type const&, Arg0 const& arg0, Args const&... args)
}
template
<
class
C
>
typename
util
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>
,
intrusive_ptr
<
C
>&>::
type
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
,
intrusive_ptr
<
C
>&
>::
type
operator
<<
(
intrusive_ptr
<
C
>&
whom
,
any_tuple
const
&
what
)
{
if
(
whom
)
whom
->
enqueue
(
self
,
what
);
...
...
@@ -598,7 +603,10 @@ operator<<(intrusive_ptr<C>& whom, any_tuple const& what)
}
template
<
class
C
>
typename
util
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>
,
intrusive_ptr
<
C
>>::
type
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
,
intrusive_ptr
<
C
>
>::
type
operator
<<
(
intrusive_ptr
<
C
>&&
whom
,
any_tuple
const
&
what
)
{
intrusive_ptr
<
C
>
tmp
(
std
::
move
(
whom
));
...
...
@@ -607,7 +615,10 @@ operator<<(intrusive_ptr<C>&& whom, any_tuple const& what)
}
template
<
class
C
>
typename
util
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>
,
intrusive_ptr
<
C
>&>::
type
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
,
intrusive_ptr
<
C
>&
>::
type
operator
<<
(
intrusive_ptr
<
C
>&
whom
,
any_tuple
&&
what
)
{
if
(
whom
)
whom
->
enqueue
(
self
,
std
::
move
(
what
));
...
...
@@ -615,7 +626,10 @@ operator<<(intrusive_ptr<C>& whom, any_tuple&& what)
}
template
<
class
C
>
typename
util
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>
,
intrusive_ptr
<
C
>>::
type
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
,
intrusive_ptr
<
C
>
>::
type
operator
<<
(
intrusive_ptr
<
C
>&&
whom
,
any_tuple
&&
what
)
{
intrusive_ptr
<
C
>
tmp
(
std
::
move
(
whom
));
...
...
cppa/detail/default_uniform_type_info_impl.hpp
View file @
332f9eee
...
...
@@ -263,7 +263,7 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
// pr.first = getter member const function pointer
// pr.second = setter member function pointer
template
<
typename
GRes
,
typename
SRes
,
typename
SArg
,
class
C
,
typename
...
Args
>
typename
util
::
enable_if
<
util
::
is_primitive
<
typename
util
::
rm_ref
<
GRes
>::
type
>
>::
type
typename
std
::
enable_if
<
util
::
is_primitive
<
typename
util
::
rm_ref
<
GRes
>::
type
>::
value
>::
type
push_back
(
const
std
::
pair
<
GRes
(
C
::*
)()
const
,
SRes
(
C
::*
)(
SArg
)
>&
pr
,
Args
&&
...
args
)
{
...
...
@@ -273,7 +273,7 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
}
template
<
typename
R
,
class
C
,
typename
...
Args
>
typename
util
::
enable_if
<
util
::
is_primitive
<
R
>
>::
type
typename
std
::
enable_if
<
util
::
is_primitive
<
R
>::
value
>::
type
push_back
(
R
C
::*
mem_ptr
,
Args
&&
...
args
)
{
m_members
.
push_back
({
new
primitive_member
<
R
>
(),
mem_ptr
});
...
...
@@ -281,7 +281,7 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
}
template
<
typename
R
,
class
C
,
typename
...
Args
>
typename
util
::
enable_if
<
is_stl_compliant_list
<
R
>
>::
type
typename
std
::
enable_if
<
is_stl_compliant_list
<
R
>::
value
>::
type
push_back
(
R
C
::*
mem_ptr
,
Args
&&
...
args
)
{
m_members
.
push_back
({
new
list_member
<
R
>
(),
mem_ptr
});
...
...
@@ -289,7 +289,7 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
}
template
<
typename
R
,
class
C
,
typename
...
Args
>
typename
util
::
enable_if
<
is_stl_compliant_map
<
R
>
>::
type
typename
std
::
enable_if
<
is_stl_compliant_map
<
R
>::
value
>::
type
push_back
(
R
C
::*
mem_ptr
,
Args
&&
...
args
)
{
m_members
.
push_back
({
new
map_member
<
R
>
(),
mem_ptr
});
...
...
@@ -297,7 +297,7 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
}
template
<
typename
R
,
class
C
,
typename
...
Args
>
typename
util
::
enable_if
<
is_invalid
<
R
>
>::
type
typename
std
::
enable_if
<
is_invalid
<
R
>::
value
>::
type
push_back
(
R
C
::*
mem_ptr
,
Args
&&
...
args
)
{
static_assert
(
util
::
is_primitive
<
R
>::
value
,
...
...
@@ -306,25 +306,25 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
}
template
<
typename
P
>
void
init_
(
typename
util
::
enable_if
<
util
::
is_primitive
<
P
>
>::
type
*
=
0
)
void
init_
(
typename
std
::
enable_if
<
util
::
is_primitive
<
P
>::
value
>::
type
*
=
0
)
{
m_members
.
push_back
(
member
::
fake_member
(
new
primitive_member
<
P
>
()));
}
template
<
typename
Map
>
void
init_
(
typename
util
::
enable_if
<
is_stl_compliant_map
<
Map
>
>::
type
*
=
0
)
void
init_
(
typename
std
::
enable_if
<
is_stl_compliant_map
<
Map
>::
value
>::
type
*
=
0
)
{
m_members
.
push_back
(
member
::
fake_member
(
new
map_member
<
Map
>
));
}
template
<
typename
List
>
void
init_
(
typename
util
::
enable_if
<
is_stl_compliant_list
<
List
>
>::
type
*
=
0
)
void
init_
(
typename
std
::
enable_if
<
is_stl_compliant_list
<
List
>::
value
>::
type
*
=
0
)
{
m_members
.
push_back
(
member
::
fake_member
(
new
list_member
<
List
>
));
}
template
<
typename
X
>
void
init_
(
typename
util
::
enable_if
<
is_invalid
<
X
>
>::
type
*
=
0
)
void
init_
(
typename
std
::
enable_if
<
is_invalid
<
X
>::
value
>::
type
*
=
0
)
{
// T is neither primitive nor a STL compliant list/map,
// so it has to be an announced type
...
...
cppa/detail/projection.hpp
View file @
332f9eee
...
...
@@ -36,6 +36,7 @@
#include "cppa/util/rm_option.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/apply_args.hpp"
#include "cppa/util/apply_tuple.hpp"
#include "cppa/util/left_or_right.hpp"
...
...
@@ -71,6 +72,9 @@ class projection
typedef
typename
tdata_from_type_list
<
ProjectionFuns
>::
type
fun_container
;
projection
()
=
default
;
projection
(
fun_container
&&
args
)
:
m_funs
(
std
::
move
(
args
))
{
}
projection
(
fun_container
const
&
args
)
:
m_funs
(
args
)
{
}
...
...
@@ -170,6 +174,7 @@ class projection<util::type_list<> >
fun
();
return
true
;
}
};
template
<
class
ProjectionFuns
,
class
List
>
...
...
cppa/
util/enable_if
.hpp
→
cppa/
detail/pseudo_tuple
.hpp
View file @
332f9eee
...
...
@@ -28,32 +28,64 @@
\******************************************************************************/
#ifndef
ENABLE_IF
_HPP
#define
ENABLE_IF
_HPP
#ifndef
PSEUDO_TUPLE
_HPP
#define
PSEUDO_TUPLE
_HPP
namespace
cppa
{
namespace
util
{
#include "cppa/util/at.hpp"
template
<
bool
Stmt
,
typename
T
=
void
>
struct
enable_if_c
namespace
cppa
{
namespace
detail
{
template
<
typename
...
T
>
struct
pseudo_tuple
{
typedef
void
*
ptr_type
;
typedef
void
const
*
const_ptr_type
;
ptr_type
data
[
sizeof
...(
T
)
>
0
?
sizeof
...(
T
)
:
1
];
inline
const_ptr_type
at
(
size_t
p
)
const
{
return
data
[
p
];
}
inline
ptr_type
mutable_at
(
size_t
p
)
{
return
const_cast
<
ptr_type
>
(
data
[
p
]);
}
inline
void
*&
operator
[](
size_t
p
)
{
return
data
[
p
];
}
};
template
<
typename
T
>
struct
enable_if_c
<
true
,
T
>
template
<
class
List
>
struct
pseudo_tuple_from_type_list
;
template
<
typename
...
Ts
>
struct
pseudo_tuple_from_type_list
<
util
::
type_list
<
Ts
...
>
>
{
typedef
T
type
;
typedef
pseudo_tuple
<
Ts
...
>
type
;
};
/**
* @ingroup MetaProgramming
* @brief SFINAE trick to enable a template function based on its
* template parameters.
*/
template
<
class
Trait
,
typename
T
=
void
>
struct
enable_if
:
enable_if_c
<
Trait
::
value
,
T
>
}
}
// namespace cppa::detail
namespace
cppa
{
template
<
size_t
N
,
typename
...
Tn
>
typename
util
::
at
<
N
,
Tn
...
>::
type
const
&
get
(
detail
::
pseudo_tuple
<
Tn
...
>
const
&
tv
)
{
};
static_assert
(
N
<
sizeof
...(
Tn
),
"N >= tv.size()"
);
return
*
reinterpret_cast
<
typename
util
::
at
<
N
,
Tn
...
>::
type
const
*>
(
tv
.
at
(
N
));
}
template
<
size_t
N
,
typename
...
Tn
>
typename
util
::
at
<
N
,
Tn
...
>::
type
&
get_ref
(
detail
::
pseudo_tuple
<
Tn
...
>&
tv
)
{
static_assert
(
N
<
sizeof
...(
Tn
),
"N >= tv.size()"
);
return
*
reinterpret_cast
<
typename
util
::
at
<
N
,
Tn
...
>::
type
*>
(
tv
.
mutable_at
(
N
));
}
}
}
// namespace cppa::util
}
// namespace cppa
#endif //
ENABLE_IF
_HPP
#endif //
PSEUDO_TUPLE
_HPP
cppa/detail/receive_loop_helper.hpp
View file @
332f9eee
...
...
@@ -66,18 +66,14 @@ struct receive_while_helper
while
(
m_stmt
())
sptr
->
dequeue
(
fun
);
}
void
operator
()(
behavior
&&
bhvr
)
template
<
typename
Arg0
,
typename
...
Args
>
void
operator
()(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
behavior
tmp
{
std
::
move
(
bhvr
)};
auto
tmp
=
match_expr_concat
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
(
*
this
)(
tmp
);
}
template
<
typename
...
Args
>
void
operator
()(
partial_function
&&
arg0
,
Args
&&
...
args
)
{
typename
select_bhvr
<
Args
...
>::
type
tmp
;
(
*
this
)(
tmp
.
splice
(
std
::
move
(
arg0
),
std
::
forward
<
Args
>
(
args
)...));
}
};
...
...
@@ -104,19 +100,14 @@ class receive_for_helper
for
(
;
begin
!=
end
;
++
begin
)
sptr
->
dequeue
(
fun
);
}
void
operator
()(
behavior
&&
bhvr
)
template
<
typename
Arg0
,
typename
...
Args
>
void
operator
()(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
behavior
tmp
{
std
::
move
(
bhvr
)};
auto
tmp
=
match_expr_concat
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
(
*
this
)(
tmp
);
}
template
<
typename
...
Args
>
void
operator
()(
partial_function
&&
arg0
,
Args
&&
...
args
)
{
typename
select_bhvr
<
Args
...
>::
type
tmp
;
(
*
this
)(
tmp
.
splice
(
std
::
move
(
arg0
),
std
::
forward
<
Args
>
(
args
)...));
}
};
class
do_receive_helper
...
...
@@ -126,14 +117,10 @@ class do_receive_helper
public:
do_receive_helper
(
behavior
&&
bhvr
)
:
m_bhvr
(
std
::
move
(
bhvr
))
{
}
template
<
typename
Arg0
,
typename
...
Args
>
do_receive_helper
(
Arg0
&&
arg0
,
Args
&&
...
args
)
template
<
typename
...
Args
>
do_receive_helper
(
Args
&&
...
args
)
:
m_bhvr
(
match_expr_concat
(
std
::
forward
<
Args
>
(
args
)...))
{
m_bhvr
.
splice
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
}
do_receive_helper
(
do_receive_helper
&&
)
=
default
;
...
...
cppa/detail/tdata.hpp
View file @
332f9eee
...
...
@@ -33,6 +33,7 @@
#include <typeinfo>
#include <functional>
#include <type_traits>
#include "cppa/get.hpp"
#include "cppa/option.hpp"
...
...
@@ -40,8 +41,6 @@
#include "cppa/util/at.hpp"
#include "cppa/util/wrapped.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/arg_match_t.hpp"
#include "cppa/detail/boxed.hpp"
...
...
@@ -151,7 +150,8 @@ struct tdata<>
tdata
(
Args
&&
...)
{
typedef
util
::
type_list
<
typename
util
::
rm_ref
<
Args
>::
type
...
>
incoming
;
static_assert
(
util
::
tl_forall
<
incoming
,
boxed_or_void
>::
value
,
typedef
typename
util
::
tl_filter_not_type
<
incoming
,
tdata
>::
type
iargs
;
static_assert
(
util
::
tl_forall
<
iargs
,
boxed_or_void
>::
value
,
"Additional unboxed arguments provided"
);
}
...
...
@@ -163,10 +163,6 @@ struct tdata<>
inline
const_iterator
end
()
const
{
return
{
this
};
}
inline
const_iterator
cend
()
const
{
return
{
this
};
}
inline
tdata
(
tdata
&
)
{
}
inline
tdata
(
tdata
&&
)
{
}
inline
tdata
(
tdata
const
&
)
{
}
inline
size_t
size
()
const
{
return
num_elements
;
}
tdata
<>&
tail
()
{
return
*
this
;
}
...
...
@@ -276,15 +272,22 @@ struct tdata<Head, Tail...> : tdata<Tail...>
//tdata(Head const& v0, Tail const&... vals) : super(vals...), head(v0) { }
template
<
typename
Arg0
,
typename
...
Args
>
tdata
(
Arg0
&&
arg0
,
Args
&&
...
args
)
:
super
(
std
::
forward
<
Args
>
(
args
)...)
tdata
(
Head
arg
)
:
super
(),
head
(
std
::
move
(
arg
))
{
}
template
<
typename
Arg0
,
typename
Arg1
,
typename
...
Args
>
tdata
(
Arg0
&&
arg0
,
Arg1
&&
arg1
,
Args
&&
...
args
)
:
super
(
std
::
forward
<
Arg1
>
(
arg1
),
std
::
forward
<
Args
>
(
args
)...)
,
head
(
td_filter
<
Head
>
(
std
::
forward
<
Arg0
>
(
arg0
)))
{
}
tdata
(
tdata
const
&
)
=
default
;
tdata
(
tdata
&&
other
)
:
super
(
std
::
move
(
other
.
tail
())),
head
(
std
::
move
(
other
.
head
))
{
}
// allow (partial) initialization from a different tdata
template
<
typename
...
Y
>
...
...
cppa/event_based_actor_base.hpp
View file @
332f9eee
...
...
@@ -62,18 +62,12 @@ class event_based_actor_base : public abstract_event_based_actor
}
/** @brief Sets the actor's behavior. */
template
<
typename
...
Args
>
void
become
(
partial_function
&&
arg0
,
Args
&&
...
args
)
template
<
typename
Arg0
,
typename
...
Args
>
void
become
(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
auto
ptr
=
new
behavior
;
ptr
->
splice
(
std
::
move
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
d_this
()
->
do_become
(
ptr
,
true
);
}
/** @brief Sets the actor's behavior to @p bhvr. */
inline
void
become
(
behavior
&&
bhvr
)
{
d_this
()
->
do_become
(
new
behavior
(
std
::
move
(
bhvr
)),
true
);
behavior
tmp
=
match_expr_concat
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
d_this
()
->
do_become
(
new
behavior
(
std
::
move
(
tmp
)),
true
);
}
};
...
...
cppa/fsm_actor.hpp
View file @
332f9eee
...
...
@@ -34,7 +34,6 @@
#include <type_traits>
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/event_based_actor.hpp"
namespace
cppa
{
...
...
cppa/get.hpp
View file @
332f9eee
...
...
@@ -38,10 +38,13 @@
namespace
cppa
{
// forward declaration of detail::tdata
namespace
detail
{
template
<
typename
...
>
class
tdata
;
}
// forward declaration of details
namespace
detail
{
template
<
typename
...
>
class
tdata
;
template
<
typename
...
>
struct
pseudo_tuple
;
}
// forward declaration of tuple
// forward declaration of
cow_
tuple
template
<
typename
...
>
class
cow_tuple
;
// forward declaration of get(detail::tdata<...> const&)
...
...
@@ -52,6 +55,10 @@ typename util::at<N, Tn...>::type const& get(detail::tdata<Tn...> const&);
template
<
size_t
N
,
typename
...
Tn
>
typename
util
::
at
<
N
,
Tn
...
>::
type
const
&
get
(
cow_tuple
<
Tn
...
>
const
&
);
// forward declarations of get(detail::pseudo_tuple<...>&)
template
<
size_t
N
,
typename
...
Tn
>
typename
util
::
at
<
N
,
Tn
...
>::
type
const
&
get
(
detail
::
pseudo_tuple
<
Tn
...
>
const
&
tv
);
// forward declarations of get_ref(detail::tdata<...>&)
template
<
size_t
N
,
typename
...
Tn
>
typename
util
::
at
<
N
,
Tn
...
>::
type
&
get_ref
(
detail
::
tdata
<
Tn
...
>&
);
...
...
@@ -60,6 +67,10 @@ typename util::at<N, Tn...>::type& get_ref(detail::tdata<Tn...>&);
template
<
size_t
N
,
typename
...
Tn
>
typename
util
::
at
<
N
,
Tn
...
>::
type
&
get_ref
(
cow_tuple
<
Tn
...
>&
);
// forward declarations of get_ref(detail::pseudo_tuple<...>&)
template
<
size_t
N
,
typename
...
Tn
>
typename
util
::
at
<
N
,
Tn
...
>::
type
&
get_ref
(
detail
::
pseudo_tuple
<
Tn
...
>&
tv
);
// support container-like access for type lists containing tokens
template
<
size_t
N
,
typename
...
Ts
>
typename
util
::
at
<
N
,
Ts
...
>::
type
get
(
util
::
type_list
<
Ts
...
>
const
&
)
...
...
cppa/guard_expr.hpp
View file @
332f9eee
...
...
@@ -41,7 +41,6 @@
#include "cppa/util/at.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/apply_tuple.hpp"
#include "cppa/detail/tdata.hpp"
...
...
@@ -427,7 +426,7 @@ template<operator_id OP, typename T1, typename T2>
guard_expr
<
OP
,
typename
detail
::
strip_and_convert
<
T1
>::
type
,
typename
detail
::
strip_and_convert
<
T2
>::
type
>
ge_concatenate
(
T1
first
,
T2
second
,
typename
util
::
enable_if_c
<
typename
std
::
enable_if
<
is_ge_type
<
T1
>::
value
||
is_ge_type
<
T2
>::
value
>::
type
*
=
0
)
{
...
...
cppa/intrusive_ptr.hpp
View file @
332f9eee
...
...
@@ -36,7 +36,6 @@
#include <stdexcept>
#include <type_traits>
#include "cppa/util/enable_if.hpp"
#include "cppa/util/comparable.hpp"
namespace
cppa
{
...
...
cppa/match.hpp
View file @
332f9eee
...
...
@@ -43,12 +43,16 @@ struct match_helper
any_tuple
tup
;
match_helper
(
any_tuple
&&
t
)
:
tup
(
std
::
move
(
t
))
{
}
match_helper
(
match_helper
&&
)
=
default
;
template
<
class
...
Args
>
void
operator
()(
partial_function
&&
pf
,
Args
&&
...
args
)
void
operator
()(
partial_function
&&
arg
)
{
partial_function
tmp
;
tmp
.
splice
(
std
::
move
(
pf
),
std
::
forward
<
Args
>
(
args
)...);
tmp
(
std
::
move
(
tup
));
partial_function
tmp
{
std
::
move
(
arg
)};
tmp
(
tup
);
}
template
<
class
Arg0
,
class
...
Args
>
void
operator
()(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
(
*
this
)(
mexpr_concat_convert
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...));
}
};
...
...
@@ -61,16 +65,20 @@ struct match_each_helper
Iterator
e
;
match_each_helper
(
Iterator
first
,
Iterator
last
)
:
i
(
first
),
e
(
last
)
{
}
match_each_helper
(
match_each_helper
&&
)
=
default
;
template
<
typename
...
Args
>
void
operator
()(
partial_function
&&
arg0
,
Args
&&
...
args
)
void
operator
()(
partial_function
&&
arg
)
{
partial_function
tmp
;
tmp
.
splice
(
std
::
move
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
partial_function
tmp
{
std
::
move
(
arg
)};
for
(;
i
!=
e
;
++
i
)
{
tmp
(
any_tuple
::
view
(
*
i
));
}
}
template
<
class
Arg0
,
class
...
Args
>
void
operator
()(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
(
*
this
)(
mexpr_concat_convert
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...));
}
};
template
<
class
Container
>
...
...
@@ -81,16 +89,20 @@ struct copying_match_each_helper
Container
vec
;
copying_match_each_helper
(
Container
tmp
)
:
vec
(
std
::
move
(
tmp
))
{
}
copying_match_each_helper
(
copying_match_each_helper
&&
)
=
default
;
template
<
typename
...
Args
>
void
operator
()(
partial_function
&&
arg0
,
Args
&&
...
args
)
void
operator
()(
partial_function
&&
arg
)
{
partial_function
tmp
;
tmp
.
splice
(
std
::
move
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
partial_function
tmp
{
std
::
move
(
arg
)};
for
(
auto
&
i
:
vec
)
{
tmp
(
any_tuple
::
view
(
i
));
}
}
template
<
class
Arg0
,
class
...
Args
>
void
operator
()(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
(
*
this
)(
mexpr_concat_convert
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...));
}
};
template
<
typename
Iterator
,
typename
Projection
>
...
...
@@ -107,16 +119,20 @@ struct pmatch_each_helper
:
i
(
first
),
e
(
last
),
p
(
std
::
forward
<
PJ
>
(
proj
))
{
}
template
<
typename
...
Args
>
void
operator
()(
partial_function
&&
arg0
,
Args
&&
...
args
)
void
operator
()(
partial_function
&&
arg
)
{
partial_function
tmp
;
tmp
.
splice
(
std
::
move
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
partial_function
tmp
{
std
::
move
(
arg
)};
for
(;
i
!=
e
;
++
i
)
{
tmp
(
any_tuple
::
view
(
p
(
*
i
)));
}
}
template
<
class
Arg0
,
class
...
Args
>
void
operator
()(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
(
*
this
)(
mexpr_concat_convert
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...));
}
};
}
}
// namespace cppa::detail
...
...
cppa/match_expr.hpp
0 → 100644
View file @
332f9eee
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef MATCH_EXPR_HPP
#define MATCH_EXPR_HPP
#include "cppa/option.hpp"
#include "cppa/pattern.hpp"
#include "cppa/guard_expr.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/tpartial_function.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/rm_option.hpp"
#include "cppa/util/purge_refs.hpp"
#include "cppa/util/left_or_right.hpp"
#include "cppa/util/deduce_ref_type.hpp"
#include "cppa/detail/projection.hpp"
#include "cppa/detail/value_guard.hpp"
#include "cppa/detail/pseudo_tuple.hpp"
namespace
cppa
{
namespace
detail
{
// covers wildcard_position::multiple and wildcard_position::in_between
template
<
wildcard_position
,
class
Pattern
,
class
FilteredPattern
>
struct
invoke_policy_impl
{
typedef
FilteredPattern
filtered_pattern
;
template
<
class
Tuple
>
static
bool
can_invoke
(
std
::
type_info
const
&
type_token
,
Tuple
const
&
tup
)
{
typedef
typename
match_impl_from_type_list
<
Tuple
,
Pattern
>::
type
mimpl
;
return
type_token
==
typeid
(
filtered_pattern
)
||
mimpl
::
_
(
tup
);
}
template
<
class
Target
,
typename
PtrType
,
class
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
type_token
,
detail
::
tuple_impl_info
,
PtrType
*
,
Tuple
&
tup
)
{
typedef
typename
match_impl_from_type_list
<
typename
std
::
remove_const
<
Tuple
>::
type
,
Pattern
>::
type
mimpl
;
util
::
fixed_vector
<
size_t
,
filtered_pattern
::
size
>
mv
;
if
(
type_token
==
typeid
(
filtered_pattern
)
||
mimpl
::
_
(
tup
,
mv
))
{
typedef
typename
pseudo_tuple_from_type_list
<
filtered_pattern
>::
type
ttup_type
;
ttup_type
ttup
;
// if we strip const here ...
for
(
size_t
i
=
0
;
i
<
filtered_pattern
::
size
;
++
i
)
{
ttup
[
i
]
=
const_cast
<
void
*>
(
tup
.
at
(
mv
[
i
]));
}
// ... we restore it here again
typedef
typename
util
::
if_else
<
std
::
is_const
<
Tuple
>
,
ttup_type
const
&
,
util
::
wrapped
<
ttup_type
&>
>::
type
ttup_ref
;
ttup_ref
ttup_fwd
=
ttup
;
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
ttup_fwd
);
}
return
false
;
}
};
template
<
class
Pattern
,
typename
...
Ts
>
struct
invoke_policy_impl
<
wildcard_position
::
nil
,
Pattern
,
util
::
type_list
<
Ts
...
>
>
{
typedef
util
::
type_list
<
Ts
...
>
filtered_pattern
;
typedef
detail
::
tdata
<
Ts
...
>
native_data_type
;
typedef
typename
detail
::
static_types_array
<
Ts
...
>
arr_type
;
template
<
class
Target
,
class
Tup
>
static
bool
invoke
(
std
::
integral_constant
<
bool
,
false
>
,
Target
&
,
Tup
&
)
{
return
false
;
}
template
<
class
Target
,
class
Tup
>
static
bool
invoke
(
std
::
integral_constant
<
bool
,
true
>
,
Target
&
target
,
Tup
&
tup
)
{
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
tup
);
}
template
<
class
Target
,
typename
PtrType
,
class
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
,
detail
::
tuple_impl_info
,
PtrType
*
,
Tuple
&
tup
,
typename
std
::
enable_if
<
std
::
is_same
<
typename
std
::
remove_const
<
Tuple
>::
type
,
detail
::
abstract_tuple
>::
value
==
false
>::
type
*
=
0
)
{
static
constexpr
bool
can_apply
=
util
::
tl_binary_forall
<
typename
util
::
tl_map
<
typename
Tuple
::
types
,
util
::
purge_refs
>::
type
,
filtered_pattern
,
std
::
is_same
>::
value
;
return
invoke
(
std
::
integral_constant
<
bool
,
can_apply
>
{},
target
,
tup
);
}
template
<
class
Target
,
typename
PtrType
,
typename
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
arg_types
,
detail
::
tuple_impl_info
timpl
,
PtrType
*
native_arg
,
Tuple
&
tup
,
typename
std
::
enable_if
<
std
::
is_same
<
typename
std
::
remove_const
<
Tuple
>::
type
,
detail
::
abstract_tuple
>::
value
>::
type
*
=
0
)
{
if
(
arg_types
==
typeid
(
filtered_pattern
))
{
if
(
native_arg
)
{
typedef
typename
util
::
if_else_c
<
std
::
is_const
<
PtrType
>::
value
,
native_data_type
const
*
,
util
::
wrapped
<
native_data_type
*>
>::
type
cast_type
;
auto
arg
=
reinterpret_cast
<
cast_type
>
(
native_arg
);
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
*
arg
);
}
// 'fall through'
}
else
if
(
timpl
==
detail
::
dynamically_typed
)
{
auto
&
arr
=
arr_type
::
arr
;
if
(
tup
.
size
()
!=
filtered_pattern
::
size
)
{
return
false
;
}
for
(
size_t
i
=
0
;
i
<
filtered_pattern
::
size
;
++
i
)
{
if
(
arr
[
i
]
!=
tup
.
type_at
(
i
))
{
return
false
;
}
}
// 'fall through'
}
else
{
return
false
;
}
typedef
pseudo_tuple
<
Ts
...
>
ttup_type
;
ttup_type
ttup
;
// if we strip const here ...
for
(
size_t
i
=
0
;
i
<
sizeof
...(
Ts
);
++
i
)
ttup
[
i
]
=
const_cast
<
void
*>
(
tup
.
at
(
i
));
// ... we restore it here again
typedef
typename
util
::
if_else
<
std
::
is_const
<
PtrType
>
,
ttup_type
const
&
,
util
::
wrapped
<
ttup_type
&>
>::
type
ttup_ref
;
ttup_ref
ttup_fwd
=
ttup
;
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
ttup_fwd
);
}
template
<
class
Tuple
>
static
bool
can_invoke
(
std
::
type_info
const
&
arg_types
,
Tuple
const
&
)
{
return
arg_types
==
typeid
(
filtered_pattern
);
}
};
template
<
>
struct
invoke_policy_impl
<
wildcard_position
::
leading
,
util
::
type_list
<
anything
>
,
util
::
type_list
<>
>
{
template
<
class
Tuple
>
static
inline
bool
can_invoke
(
std
::
type_info
const
&
,
Tuple
const
&
)
{
return
true
;
}
template
<
class
Target
,
typename
PtrType
,
typename
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
,
detail
::
tuple_impl_info
,
PtrType
*
,
Tuple
&
)
{
return
target
();
}
};
template
<
class
Pattern
,
typename
...
Ts
>
struct
invoke_policy_impl
<
wildcard_position
::
trailing
,
Pattern
,
util
::
type_list
<
Ts
...
>
>
{
typedef
util
::
type_list
<
Ts
...
>
filtered_pattern
;
template
<
class
Tuple
>
static
bool
can_invoke
(
std
::
type_info
const
&
arg_types
,
Tuple
const
&
tup
)
{
if
(
arg_types
==
typeid
(
filtered_pattern
))
{
return
true
;
}
typedef
detail
::
static_types_array
<
Ts
...
>
arr_type
;
auto
&
arr
=
arr_type
::
arr
;
if
(
tup
.
size
()
<
filtered_pattern
::
size
)
{
return
false
;
}
for
(
size_t
i
=
0
;
i
<
filtered_pattern
::
size
;
++
i
)
{
if
(
arr
[
i
]
!=
tup
.
type_at
(
i
))
{
return
false
;
}
}
return
true
;
}
template
<
class
Target
,
typename
PtrType
,
class
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
arg_types
,
detail
::
tuple_impl_info
,
PtrType
*
,
Tuple
&
tup
)
{
if
(
!
can_invoke
(
arg_types
,
tup
))
return
false
;
typedef
pseudo_tuple
<
Ts
...
>
ttup_type
;
ttup_type
ttup
;
for
(
size_t
i
=
0
;
i
<
sizeof
...(
Ts
);
++
i
)
ttup
[
i
]
=
const_cast
<
void
*>
(
tup
.
at
(
i
));
// ensure const-correctness
typedef
typename
util
::
if_else
<
std
::
is_const
<
Tuple
>
,
ttup_type
const
&
,
util
::
wrapped
<
ttup_type
&>
>::
type
ttup_ref
;
ttup_ref
ttup_fwd
=
ttup
;
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
ttup_fwd
);
}
};
template
<
class
Pattern
,
typename
...
Ts
>
struct
invoke_policy_impl
<
wildcard_position
::
leading
,
Pattern
,
util
::
type_list
<
Ts
...
>
>
{
typedef
util
::
type_list
<
Ts
...
>
filtered_pattern
;
template
<
class
Tuple
>
static
bool
can_invoke
(
std
::
type_info
const
&
arg_types
,
Tuple
const
&
tup
)
{
if
(
arg_types
==
typeid
(
filtered_pattern
))
{
return
true
;
}
typedef
detail
::
static_types_array
<
Ts
...
>
arr_type
;
auto
&
arr
=
arr_type
::
arr
;
if
(
tup
.
size
()
<
filtered_pattern
::
size
)
{
return
false
;
}
size_t
i
=
tup
.
size
()
-
filtered_pattern
::
size
;
size_t
j
=
0
;
while
(
j
<
filtered_pattern
::
size
)
{
if
(
arr
[
i
++
]
!=
tup
.
type_at
(
j
++
))
{
return
false
;
}
}
return
true
;
}
template
<
class
Target
,
typename
PtrType
,
class
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
arg_types
,
detail
::
tuple_impl_info
,
PtrType
*
,
Tuple
&
tup
)
{
if
(
!
can_invoke
(
arg_types
,
tup
))
return
false
;
typedef
pseudo_tuple
<
Ts
...
>
ttup_type
;
ttup_type
ttup
;
size_t
i
=
tup
.
size
()
-
filtered_pattern
::
size
;
size_t
j
=
0
;
while
(
j
<
filtered_pattern
::
size
)
{
ttup
[
j
++
]
=
const_cast
<
void
*>
(
tup
.
at
(
i
++
));
}
// ensure const-correctness
typedef
typename
util
::
if_else
<
std
::
is_const
<
Tuple
>
,
ttup_type
const
&
,
util
::
wrapped
<
ttup_type
&>
>::
type
ttup_ref
;
ttup_ref
ttup_fwd
=
ttup
;
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
ttup_fwd
);
}
};
template
<
class
Pattern
>
struct
invoke_policy
:
invoke_policy_impl
<
get_wildcard_position
<
Pattern
>
(),
Pattern
,
typename
util
::
tl_filter_not_type
<
Pattern
,
anything
>::
type
>
{
};
template
<
class
Pattern
,
class
Projection
,
class
PartialFunction
>
struct
projection_partial_function_pair
:
std
::
pair
<
Projection
,
PartialFunction
>
{
template
<
typename
...
Args
>
projection_partial_function_pair
(
Args
&&
...
args
)
:
std
::
pair
<
Projection
,
PartialFunction
>
(
std
::
forward
<
Args
>
(
args
)...)
{
}
typedef
Pattern
pattern_type
;
};
template
<
class
Expr
,
class
Guard
,
class
Transformers
,
class
Pattern
>
struct
get_case_
{
typedef
typename
util
::
get_callable_trait
<
Expr
>::
type
ctrait
;
typedef
typename
util
::
tl_filter_not_type
<
Pattern
,
anything
>::
type
filtered_pattern
;
typedef
typename
util
::
tl_pad_right
<
Transformers
,
filtered_pattern
::
size
>::
type
padded_transformers
;
typedef
typename
util
::
tl_map
<
filtered_pattern
,
std
::
add_const
,
std
::
add_lvalue_reference
>::
type
base_signature
;
typedef
typename
util
::
tl_map_conditional
<
typename
util
::
tl_pad_left
<
typename
ctrait
::
arg_types
,
filtered_pattern
::
size
>::
type
,
std
::
is_lvalue_reference
,
false
,
std
::
add_const
,
std
::
add_lvalue_reference
>::
type
padded_expr_args
;
// override base signature with required argument types of Expr
// and result types of transformation
typedef
typename
util
::
tl_zip
<
typename
util
::
tl_map
<
padded_transformers
,
util
::
get_result_type
,
util
::
rm_option
,
std
::
add_lvalue_reference
>::
type
,
typename
util
::
tl_zip
<
padded_expr_args
,
base_signature
,
util
::
left_or_right
>::
type
,
util
::
left_or_right
>::
type
partial_fun_signature
;
// 'inherit' mutable references from partial_fun_signature
// for arguments without transformation
typedef
typename
util
::
tl_zip
<
typename
util
::
tl_zip
<
padded_transformers
,
partial_fun_signature
,
util
::
if_not_left
>::
type
,
base_signature
,
util
::
deduce_ref_type
>::
type
projection_signature
;
typedef
typename
projection_from_type_list
<
padded_transformers
,
projection_signature
>::
type
type1
;
typedef
typename
get_tpartial_function
<
Expr
,
Guard
,
partial_fun_signature
>::
type
type2
;
typedef
projection_partial_function_pair
<
Pattern
,
type1
,
type2
>
type
;
};
template
<
bool
IsComplete
,
class
Expr
,
class
Guard
,
class
Transformers
,
class
Pattern
>
struct
get_case
{
typedef
typename
get_case_
<
Expr
,
Guard
,
Transformers
,
Pattern
>::
type
type
;
};
template
<
class
Expr
,
class
Guard
,
class
Transformers
,
class
Pattern
>
struct
get_case
<
false
,
Expr
,
Guard
,
Transformers
,
Pattern
>
{
typedef
typename
util
::
tl_pop_back
<
Pattern
>::
type
lhs_pattern
;
typedef
typename
util
::
tl_map
<
typename
util
::
get_arg_types
<
Expr
>::
types
,
util
::
rm_ref
>::
type
rhs_pattern
;
typedef
typename
get_case_
<
Expr
,
Guard
,
Transformers
,
typename
util
::
tl_concat
<
lhs_pattern
,
rhs_pattern
>::
type
>::
type
type
;
};
/*
template<class Expr>
struct get_case<true, Expr, value_guard<util::type_list<> >,
util::type_list<>, util::type_list<anything> >
{
typedef typename get_case_<
Expr,
value_guard<util::type_list<> >,
util::type_list<>,
util::type_list<anything>
>::type
type;
};
*/
template
<
typename
First
,
typename
Second
>
struct
pjf_same_pattern
:
std
::
is_same
<
typename
First
::
second
::
pattern_type
,
typename
Second
::
second
::
pattern_type
>
{
};
// last invocation step; evaluates a {projection, tpartial_function} pair
template
<
typename
Data
>
struct
invoke_helper3
{
Data
const
&
data
;
invoke_helper3
(
Data
const
&
mdata
)
:
data
(
mdata
)
{
}
template
<
size_t
Pos
,
typename
T
,
typename
...
Args
>
inline
bool
operator
()(
util
::
type_pair
<
std
::
integral_constant
<
size_t
,
Pos
>
,
T
>
,
Args
&&
...
args
)
const
{
auto
const
&
target
=
get
<
Pos
>
(
data
);
return
target
.
first
(
target
.
second
,
std
::
forward
<
Args
>
(
args
)...);
//return (get<Pos>(data))(args...);
}
};
template
<
class
Data
,
class
Token
,
class
Pattern
>
struct
invoke_helper2
{
typedef
Pattern
pattern_type
;
typedef
typename
util
::
tl_filter_not_type
<
pattern_type
,
anything
>::
type
arg_types
;
Data
const
&
data
;
invoke_helper2
(
Data
const
&
mdata
)
:
data
(
mdata
)
{
}
template
<
typename
...
Args
>
bool
invoke
(
Args
&&
...
args
)
const
{
typedef
invoke_policy
<
Pattern
>
impl
;
return
impl
::
invoke
(
*
this
,
std
::
forward
<
Args
>
(
args
)...);
}
// resolved argument list (called from invoke_policy)
template
<
typename
...
Args
>
bool
operator
()(
Args
&&
...
args
)
const
{
//static_assert(false, "foo");
Token
token
;
invoke_helper3
<
Data
>
fun
{
data
};
return
util
::
static_foreach
<
0
,
Token
::
size
>::
eval_or
(
token
,
fun
,
std
::
forward
<
Args
>
(
args
)...);
}
};
// invokes a group of {projection, tpartial_function} pairs
template
<
typename
Data
>
struct
invoke_helper
{
Data
const
&
data
;
std
::
uint64_t
bitfield
;
invoke_helper
(
Data
const
&
mdata
,
std
::
uint64_t
bits
)
:
data
(
mdata
),
bitfield
(
bits
)
{
}
// token: type_list<type_pair<integral_constant<size_t, X>,
// std::pair<projection, tpartial_function>>,
// ...>
// all {projection, tpartial_function} pairs have the same pattern
// thus, can be invoked from same data
template
<
class
Token
,
typename
...
Args
>
bool
operator
()(
Token
,
Args
&&
...
args
)
{
typedef
typename
Token
::
head
type_pair
;
typedef
typename
type_pair
::
second
leaf_pair
;
if
(
bitfield
&
0x01
)
//if (*enabled++)
{
// next invocation step
invoke_helper2
<
Data
,
Token
,
typename
leaf_pair
::
pattern_type
>
fun
{
data
};
return
fun
.
invoke
(
std
::
forward
<
Args
>
(
args
)...);
}
bitfield
>>=
1
;
//++enabled;
return
false
;
}
};
struct
can_invoke_helper
{
std
::
uint64_t
&
bitfield
;
size_t
i
;
can_invoke_helper
(
std
::
uint64_t
&
mbitfield
)
:
bitfield
(
mbitfield
),
i
(
0
)
{
}
template
<
class
Token
,
typename
...
Args
>
void
operator
()(
Token
,
Args
&&
...
args
)
{
typedef
typename
Token
::
head
type_pair
;
typedef
typename
type_pair
::
second
leaf_pair
;
typedef
invoke_policy
<
typename
leaf_pair
::
pattern_type
>
impl
;
if
(
impl
::
can_invoke
(
std
::
forward
<
Args
>
(
args
)...))
{
bitfield
|=
(
0x01
<<
i
);
}
++
i
;
}
};
template
<
typename
T
>
struct
is_manipulator_case
{
static
constexpr
bool
value
=
T
::
second_type
::
manipulates_args
;
};
template
<
bool
IsManipulator
,
typename
T0
,
typename
T1
>
struct
mexpr_fwd_
{
typedef
T1
type
;
};
template
<
typename
T
>
struct
mexpr_fwd_
<
false
,
T
const
&
,
T
>
{
typedef
std
::
reference_wrapper
<
const
T
>
type
;
};
template
<
typename
T
>
struct
mexpr_fwd_
<
true
,
T
&
,
T
>
{
typedef
std
::
reference_wrapper
<
T
>
type
;
};
template
<
bool
IsManipulator
,
typename
T
>
struct
mexpr_fwd
{
typedef
typename
mexpr_fwd_
<
IsManipulator
,
T
,
typename
detail
::
implicit_conversions
<
typename
util
::
rm_ref
<
T
>::
type
>::
type
>::
type
type
;
};
}
}
// namespace cppa::detail
namespace
cppa
{
/**
* @brief A function that works on the projection of given data rather than
* on the data itself.
*/
template
<
class
...
Cases
>
class
match_expr
{
static_assert
(
sizeof
...(
Cases
)
<
64
,
"too many functions"
);
public:
typedef
util
::
type_list
<
Cases
...
>
cases_list
;
typedef
typename
util
::
tl_group_by
<
typename
util
::
tl_zip_with_index
<
cases_list
>::
type
,
detail
::
pjf_same_pattern
>::
type
eval_order
;
static
constexpr
bool
has_manipulator
=
util
::
tl_exists
<
cases_list
,
detail
::
is_manipulator_case
>::
value
;
template
<
typename
...
Args
>
match_expr
(
Args
&&
...
args
)
:
m_cases
(
std
::
forward
<
Args
>
(
args
)...)
{
init
();
}
match_expr
(
match_expr
&&
other
)
:
m_cases
(
std
::
move
(
other
.
m_cases
))
{
init
();
}
match_expr
(
match_expr
const
&
other
)
:
m_cases
(
other
.
m_cases
)
{
init
();
}
bool
invoke
(
any_tuple
const
&
tup
)
{
return
_invoke
(
tup
);
}
bool
invoke
(
any_tuple
&
tup
)
{
return
_invoke
(
tup
);
}
bool
invoke
(
any_tuple
&&
tup
)
{
any_tuple
tmp
{
tup
};
return
_invoke
(
tmp
);
}
bool
can_invoke
(
any_tuple
const
tup
)
{
auto
&
type_token
=
*
(
tup
.
type_token
());
eval_order
token
;
std
::
uint64_t
tmp
=
0
;
detail
::
can_invoke_helper
fun
{
tmp
};
util
::
static_foreach
<
0
,
eval_order
::
size
>
::
_
(
token
,
fun
,
type_token
,
tup
);
return
tmp
!=
0
;
}
bool
operator
()(
any_tuple
const
&
tup
)
{
return
_invoke
(
tup
);
}
bool
operator
()(
any_tuple
&
tup
)
{
return
_invoke
(
tup
);
}
bool
operator
()(
any_tuple
&&
tup
)
{
any_tuple
tmp
{
tup
};
return
_invoke
(
tmp
);
}
template
<
typename
...
Args
>
bool
operator
()(
Args
&&
...
args
)
{
typedef
detail
::
tdata
<
typename
detail
::
mexpr_fwd
<
has_manipulator
,
Args
>::
type
...
>
tuple_type
;
// applies implicit conversions etc
tuple_type
tup
{
std
::
forward
<
Args
>
(
args
)...};
auto
&
type_token
=
typeid
(
typename
tuple_type
::
types
);
auto
enabled_begin
=
get_cache_entry
(
&
type_token
,
tup
);
typedef
typename
util
::
if_else_c
<
has_manipulator
,
tuple_type
&
,
util
::
wrapped
<
tuple_type
const
&>
>::
type
ref_type
;
typedef
typename
util
::
if_else_c
<
has_manipulator
,
void
*
,
util
::
wrapped
<
void
const
*>
>::
type
ptr_type
;
eval_order
token
;
detail
::
invoke_helper
<
decltype
(
m_cases
)
>
fun
{
m_cases
,
enabled_begin
};
return
util
::
static_foreach
<
0
,
eval_order
::
size
>
::
eval_or
(
token
,
fun
,
type_token
,
detail
::
statically_typed
,
static_cast
<
ptr_type
>
(
nullptr
),
static_cast
<
ref_type
>
(
tup
));
}
template
<
class
...
OtherCases
>
match_expr
<
Cases
...,
OtherCases
...
>
or_else
(
match_expr
<
OtherCases
...
>
const
&
other
)
const
{
detail
::
tdata
<
ge_reference_wrapper
<
Cases
>
...,
ge_reference_wrapper
<
OtherCases
>
...
>
all_cases
;
collect_tdata
(
all_cases
,
m_cases
,
other
.
cases
());
return
{
all_cases
};
}
inline
detail
::
tdata
<
Cases
...
>
const
&
cases
()
const
{
return
m_cases
;
}
struct
pfun_impl
:
partial_function
::
impl
{
match_expr
pfun
;
template
<
typename
Arg
>
pfun_impl
(
Arg
const
&
from
)
:
pfun
(
from
)
{
}
bool
invoke
(
any_tuple
&
tup
)
{
return
pfun
.
invoke
(
tup
);
}
bool
invoke
(
any_tuple
const
&
tup
)
{
return
pfun
.
invoke
(
tup
);
}
bool
defined_at
(
any_tuple
const
&
tup
)
{
return
pfun
.
can_invoke
(
tup
);
}
};
operator
partial_function
()
const
{
return
{
partial_function
::
impl_ptr
{
new
pfun_impl
(
*
this
)}};
}
private:
// structure: tdata< tdata<type_list<...>, ...>,
// tdata<type_list<...>, ...>,
// ...>
detail
::
tdata
<
Cases
...
>
m_cases
;
static
constexpr
size_t
cache_size
=
10
;
//typedef std::array<bool, eval_order::size> cache_entry;
//typedef typename cache_entry::iterator cache_entry_iterator;
//typedef std::pair<std::type_info const*, cache_entry> cache_element;
// std::uint64_t is used as a bitmask to enable/disable groups
typedef
std
::
pair
<
std
::
type_info
const
*
,
std
::
uint64_t
>
cache_element
;
util
::
fixed_vector
<
cache_element
,
cache_size
>
m_cache
;
// ring buffer like access to m_cache
size_t
m_cache_begin
;
size_t
m_cache_end
;
cache_element
m_dummy
;
static
inline
void
advance_
(
size_t
&
i
)
{
i
=
(
i
+
1
)
%
cache_size
;
}
inline
size_t
find_token_pos
(
std
::
type_info
const
*
type_token
)
{
for
(
size_t
i
=
m_cache_begin
;
i
!=
m_cache_end
;
advance_
(
i
))
{
if
(
m_cache
[
i
].
first
==
type_token
)
return
i
;
}
return
m_cache_end
;
}
template
<
class
Tuple
>
std
::
uint64_t
get_cache_entry
(
std
::
type_info
const
*
type_token
,
Tuple
const
&
value
)
{
CPPA_REQUIRE
(
type_token
!=
nullptr
);
if
(
value
.
impl_type
()
==
detail
::
dynamically_typed
)
{
return
m_dummy
.
second
;
// all groups enabled
}
size_t
i
=
find_token_pos
(
type_token
);
// if we didn't found a cache entry ...
if
(
i
==
m_cache_end
)
{
// ... 'create' one (override oldest element in cache if full)
advance_
(
m_cache_end
);
if
(
m_cache_end
==
m_cache_begin
)
advance_
(
m_cache_begin
);
m_cache
[
i
].
first
=
type_token
;
m_cache
[
i
].
second
=
0
;
eval_order
token
;
detail
::
can_invoke_helper
fun
{
m_cache
[
i
].
second
};
util
::
static_foreach
<
0
,
eval_order
::
size
>
::
_
(
token
,
fun
,
*
type_token
,
value
);
}
return
m_cache
[
i
].
second
;
}
void
init
()
{
m_dummy
.
second
=
std
::
numeric_limits
<
std
::
uint64_t
>::
max
();
m_cache
.
resize
(
cache_size
);
for
(
auto
&
entry
:
m_cache
)
{
entry
.
first
=
nullptr
;
}
m_cache_begin
=
m_cache_end
=
0
;
}
template
<
typename
AbstractTuple
,
typename
NativeDataPtr
>
bool
_do_invoke
(
AbstractTuple
&
vals
,
NativeDataPtr
ndp
)
{
std
::
type_info
const
*
type_token
=
vals
.
type_token
();
auto
bitfield
=
get_cache_entry
(
type_token
,
vals
);
eval_order
token
;
detail
::
invoke_helper
<
decltype
(
m_cases
)
>
fun
{
m_cases
,
bitfield
};
return
util
::
static_foreach
<
0
,
eval_order
::
size
>
::
eval_or
(
token
,
fun
,
*
type_token
,
vals
.
impl_type
(),
ndp
,
vals
);
}
template
<
typename
AnyTuple
>
bool
_invoke
(
AnyTuple
&
tup
,
typename
std
::
enable_if
<
std
::
is_const
<
AnyTuple
>::
value
==
false
&&
has_manipulator
==
true
>::
type
*
=
0
)
{
tup
.
force_detach
();
auto
&
vals
=
*
(
tup
.
vals
());
return
_do_invoke
(
vals
,
vals
.
mutable_native_data
());
}
template
<
typename
AnyTuple
>
bool
_invoke
(
AnyTuple
&
tup
,
typename
std
::
enable_if
<
std
::
is_const
<
AnyTuple
>::
value
==
false
&&
has_manipulator
==
false
>::
type
*
=
0
)
{
return
_invoke
(
static_cast
<
AnyTuple
const
&>
(
tup
));
}
template
<
typename
AnyTuple
>
bool
_invoke
(
AnyTuple
&
tup
,
typename
std
::
enable_if
<
std
::
is_const
<
AnyTuple
>::
value
==
true
&&
has_manipulator
==
false
>::
type
*
=
0
)
{
auto
const
&
cvals
=
*
(
tup
.
cvals
());
return
_do_invoke
(
cvals
,
cvals
.
native_data
());
}
template
<
typename
AnyTuple
>
bool
_invoke
(
AnyTuple
&
tup
,
typename
std
::
enable_if
<
std
::
is_const
<
AnyTuple
>::
value
==
true
&&
has_manipulator
==
true
>::
type
*
=
0
)
{
any_tuple
tup_copy
{
tup
};
return
_invoke
(
tup_copy
);
}
};
template
<
class
List
>
struct
match_expr_from_type_list
;
template
<
typename
...
Args
>
struct
match_expr_from_type_list
<
util
::
type_list
<
Args
...
>
>
{
typedef
match_expr
<
Args
...
>
type
;
};
template
<
typename
...
Lhs
,
typename
...
Rhs
>
inline
match_expr
<
Lhs
...,
Rhs
...
>
operator
,(
match_expr
<
Lhs
...
>
const
&
lhs
,
match_expr
<
Rhs
...
>
const
&
rhs
)
{
return
lhs
.
or_else
(
rhs
);
}
template
<
typename
Arg0
,
typename
...
Args
>
typename
match_expr_from_type_list
<
typename
util
::
tl_concat
<
typename
Arg0
::
cases_list
,
typename
Args
::
cases_list
...
>::
type
>::
type
mexpr_concat
(
Arg0
const
&
arg0
,
Args
const
&
...
args
)
{
typename
detail
::
tdata_from_type_list
<
typename
util
::
tl_map
<
typename
util
::
tl_concat
<
typename
Arg0
::
cases_list
,
typename
Args
::
cases_list
...
>::
type
,
gref_wrapped
>::
type
>::
type
all_cases
;
detail
::
collect_tdata
(
all_cases
,
arg0
.
cases
(),
args
.
cases
()...);
return
{
all_cases
};
}
template
<
typename
Arg0
,
typename
...
Args
>
partial_function
mexpr_concat_convert
(
Arg0
const
&
arg0
,
Args
const
&
...
args
)
{
typename
detail
::
tdata_from_type_list
<
typename
util
::
tl_map
<
typename
util
::
tl_concat
<
typename
Arg0
::
cases_list
,
typename
Args
::
cases_list
...
>::
type
,
gref_wrapped
>::
type
>::
type
all_cases
;
typedef
typename
match_expr_from_type_list
<
typename
util
::
tl_concat
<
typename
Arg0
::
cases_list
,
typename
Args
::
cases_list
...
>::
type
>::
type
combined_type
;
typedef
typename
combined_type
::
pfun_impl
impl_type
;
detail
::
collect_tdata
(
all_cases
,
arg0
.
cases
(),
args
.
cases
()...);
return
{
partial_function
::
impl_ptr
{
new
impl_type
(
all_cases
)}};
}
}
// namespace cppa
#endif // MATCH_EXPR_HPP
cppa/on.hpp
View file @
332f9eee
...
...
@@ -33,6 +33,7 @@
#include <chrono>
#include <memory>
#include <type_traits>
#include "cppa/atom.hpp"
#include "cppa/pattern.hpp"
...
...
@@ -40,22 +41,62 @@
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/guard_expr.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/arg_match_t.hpp"
#include "cppa/util/callable_trait.hpp"
#include "cppa/detail/boxed.hpp"
#include "cppa/detail/unboxed.hpp"
#include "cppa/detail/invokable.hpp"
#include "cppa/detail/value_guard.hpp"
#include "cppa/detail/ref_counted_impl.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace
cppa
{
namespace
detail
{
template
<
bool
IsFun
,
typename
T
>
struct
add_ptr_to_fun_
{
typedef
T
*
type
;
};
template
<
typename
T
>
struct
add_ptr_to_fun_
<
false
,
T
>
{
typedef
T
type
;
};
template
<
typename
T
>
struct
add_ptr_to_fun
:
add_ptr_to_fun_
<
std
::
is_function
<
T
>::
value
,
T
>
{
};
template
<
bool
ToVoid
,
typename
T
>
struct
to_void_impl
{
typedef
util
::
void_type
type
;
};
template
<
typename
T
>
struct
to_void_impl
<
false
,
T
>
{
typedef
typename
add_ptr_to_fun
<
T
>::
type
type
;
};
template
<
typename
T
>
struct
not_callable_to_void
:
to_void_impl
<
detail
::
is_boxed
<
T
>::
value
||
!
util
::
is_callable
<
T
>::
value
,
T
>
{
};
template
<
typename
T
>
struct
boxed_and_callable_to_void
:
to_void_impl
<
detail
::
is_boxed
<
T
>::
value
||
util
::
is_callable
<
T
>::
value
,
T
>
{
};
class
behavior_rvalue_builder
{
...
...
@@ -75,144 +116,106 @@ class behavior_rvalue_builder
};
template
<
typename
...
TypeList
>
class
rvalue_builder
{
typedef
util
::
arg_match_t
arg_match_t
;
struct
rvalue_builder_args_ctor
{
};
typedef
util
::
type_list
<
typename
detail
::
implicit_conversions
<
TypeList
>::
type
...
>
raw_types
;
template
<
class
Guard
,
class
Transformers
,
class
Pattern
>
struct
rvalue_builder
{
static
constexpr
bool
is_complete
=
!
std
::
is_same
<
arg_match_t
,
typename
raw_types
::
back
>::
value
;
typedef
typename
util
::
if_else_c
<
is_complete
==
false
,
typename
util
::
tl_pop_back
<
raw_types
>::
type
,
util
::
wrapped
<
raw_types
>
>::
type
types
;
!
std
::
is_same
<
util
::
arg_match_t
,
typename
Pattern
::
back
>::
value
;
static_assert
(
util
::
tl_find
<
types
,
arg_match_t
>::
value
==
-
1
,
"arg_match is allowed only as last parameter for on()"
);
typedef
typename
util
::
tl_apply
<
Transformers
,
tdata
>::
type
fun_container
;
typedef
typename
pattern_from_type_list
<
types
>::
type
pattern_type
;
Guard
m_guard
;
fun_container
m_funs
;
typedef
std
::
unique_ptr
<
value_matcher
>
vm_ptr
;
public:
vm_ptr
m_vm
;
rvalue_builder
()
=
default
;
template
<
typename
F
>
partial_function
cr_rvalue
(
F
&&
f
,
std
::
integral_constant
<
bool
,
true
>
)
template
<
typename
...
Args
>
rvalue_builder
(
rvalue_builder_args_ctor
,
Args
const
&
...
args
)
:
m_guard
(
args
...)
,
m_funs
(
args
...)
{
return
get_invokable_impl
<
pattern_type
>
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
m_vm
));
}
template
<
typename
F
>
partial_function
cr_rvalue
(
F
&&
f
,
std
::
integral_constant
<
bool
,
false
>
)
rvalue_builder
(
Guard
arg0
,
fun_container
arg1
)
:
m_guard
(
std
::
move
(
arg0
)),
m_funs
(
std
::
move
(
arg1
)
)
{
using
namespace
::
cppa
::
util
;
typedef
typename
get_callable_trait
<
F
>::
type
ctrait
;
typedef
typename
ctrait
::
arg_types
raw_arg_types
;
static_assert
(
raw_types
::
size
>
0
,
"functor has no arguments"
);
typedef
typename
tl_map
<
raw_arg_types
,
rm_ref
>::
type
arg_types
;
typedef
typename
tl_concat
<
types
,
arg_types
>::
type
full_types
;
typedef
typename
pattern_from_type_list
<
full_types
>::
type
epattern
;
return
get_invokable_impl
<
epattern
>
(
std
::
forward
<
F
>
(
f
),
std
::
move
(
m_vm
));
}
public:
//template<operator_id OP, typename F, typename S>
//rvalue_builder& when(guard_expr<OP, F, S> ge)
template
<
typename
Fun
>
rvalue_builder
&
when
(
Fun
&&
fun
)
{
//TODO: static_assert
typedef
typename
util
::
rm_ref
<
Fun
>::
type
fun_type
;
if
(
m_vm
)
template
<
typename
NewGuard
>
rvalue_builder
<
guard_expr
<
logical_and_op
,
guard_expr
<
exec_xfun_op
,
Guard
,
util
::
void_type
>
,
NewGuard
>
,
Transformers
,
Pattern
>
when
(
NewGuard
ng
,
typename
std
::
enable_if
<
std
::
is_same
<
NewGuard
,
NewGuard
>::
value
&&
!
std
::
is_same
<
Guard
,
value_guard
<
util
::
type_list
<>
>>::
value
>::
type
*
=
0
)
const
{
struct
impl1
:
value_matcher
{
vm_ptr
m_ptr
;
fun_type
m_fun
;
impl1
(
vm_ptr
&&
ptr
,
Fun
&&
f
)
:
m_ptr
(
std
::
move
(
ptr
)),
m_fun
(
std
::
forward
<
Fun
>
(
f
))
{
}
bool
operator
()(
any_tuple
const
&
tup
)
const
{
if
((
*
m_ptr
)(
tup
))
{
auto
ttup
=
tuple_cast
(
tup
,
types
{});
if
(
ttup
)
{
return
util
::
unchecked_apply_tuple
<
bool
>
(
m_fun
,
*
ttup
);
}
}
return
false
;
}
};
m_vm
.
reset
(
new
impl1
{
std
::
move
(
m_vm
),
std
::
forward
<
Fun
>
(
fun
)});
}
else
{
struct
impl2
:
value_matcher
{
fun_type
m_fun
;
impl2
(
Fun
&&
f
)
:
m_fun
(
std
::
forward
<
Fun
>
(
f
))
{
}
bool
operator
()(
any_tuple
const
&
tup
)
const
{
auto
ttup
=
tuple_cast
(
tup
,
types
{});
if
(
ttup
)
{
return
util
::
unchecked_apply_tuple
<
bool
>
(
m_fun
,
*
ttup
);
}
return
false
;
}
};
m_vm
.
reset
(
new
impl2
{
std
::
forward
<
Fun
>
(
fun
)});
}
return
*
this
;
return
{(
gcall
(
m_guard
)
&&
ng
),
std
::
move
(
m_funs
)};
}
template
<
typename
...
Args
>
rvalue_builder
(
Args
&&
...
args
)
:
m_vm
(
pattern_type
::
get_value_matcher
(
std
::
forward
<
Args
>
(
args
)...))
template
<
typename
NewGuard
>
rvalue_builder
<
NewGuard
,
Transformers
,
Pattern
>
when
(
NewGuard
ng
,
typename
std
::
enable_if
<
std
::
is_same
<
NewGuard
,
NewGuard
>::
value
&&
std
::
is_same
<
Guard
,
value_guard
<
util
::
type_list
<>
>>::
value
>::
type
*
=
0
)
const
{
return
{
std
::
move
(
ng
),
std
::
move
(
m_funs
)};
}
template
<
typename
F
>
partial_function
operator
>>
(
F
&&
f
)
template
<
typename
Expr
>
match_expr
<
typename
get_case
<
is_complete
,
Expr
,
Guard
,
Transformers
,
Pattern
>::
type
>
operator
>>
(
Expr
expr
)
const
{
std
::
integral_constant
<
bool
,
is_complete
>
token
;
return
cr_rvalue
(
std
::
forward
<
F
>
(
f
),
token
);
typedef
typename
get_case
<
is_complete
,
Expr
,
Guard
,
Transformers
,
Pattern
>::
type
tpair
;
return
tpair
{
typename
tpair
::
first_type
{
m_funs
},
typename
tpair
::
second_type
{
std
::
move
(
expr
),
std
::
move
(
m_guard
)}};
}
};
template
<
>
class
rvalue_builder
<
anything
>
template
<
bool
IsCallable
,
typename
T
>
struct
pattern_type_
{
typedef
util
::
get_callable_trait
<
T
>
ctrait
;
typedef
typename
ctrait
::
arg_types
args
;
static_assert
(
args
::
size
==
1
,
"only unary functions allowed"
);
typedef
typename
util
::
rm_ref
<
typename
args
::
head
>::
type
type
;
};
typedef
pattern
<
anything
>
pattern_type
;
public:
constexpr
rvalue_builder
()
{
}
template
<
typename
F
>
partial_function
operator
>>
(
F
&&
f
)
{
return
get_invokable_impl
<
pattern_type
>
(
std
::
forward
<
F
>
(
f
));
}
template
<
typename
T
>
struct
pattern_type_
<
false
,
T
>
{
typedef
typename
implicit_conversions
<
typename
util
::
rm_ref
<
typename
detail
::
unboxed
<
T
>::
type
>::
type
>::
type
type
;
};
template
<
typename
T
>
struct
pattern_type
:
pattern_type_
<
util
::
is_callable
<
T
>::
value
&&
!
detail
::
is_boxed
<
T
>::
value
,
T
>
{
};
class
on_the_fly_rvalue_builder
...
...
@@ -224,16 +227,30 @@ class on_the_fly_rvalue_builder
{
}
template
<
typename
F
>
partial_function
operator
>>
(
F
&&
f
)
const
template
<
typename
Expr
>
match_expr
<
typename
get_case
<
false
,
Expr
,
value_guard
<
util
::
type_list
<>
>
,
util
::
type_list
<>
,
util
::
type_list
<>
>::
type
>
operator
>>
(
Expr
expr
)
const
{
using
namespace
::
cppa
::
util
;
typedef
typename
get_callable_trait
<
F
>::
type
ctrait
;
typedef
typename
ctrait
::
arg_types
raw_types
;
static_assert
(
raw_types
::
size
>
0
,
"functor has no arguments"
);
typedef
typename
tl_map
<
raw_types
,
rm_ref
>::
type
types
;
typedef
typename
pattern_from_type_list
<
types
>::
type
pattern_type
;
return
get_invokable_impl
<
pattern_type
>
(
std
::
forward
<
F
>
(
f
));
typedef
typename
get_case
<
false
,
Expr
,
value_guard
<
util
::
type_list
<>
>
,
util
::
type_list
<>
,
util
::
type_list
<>
>::
type
result
;
return
result
{
typename
result
::
first_type
{},
typename
result
::
second_type
{
std
::
move
(
expr
),
value_guard
<
util
::
type_list
<>
>
{}}};
}
};
...
...
@@ -316,44 +333,59 @@ constexpr boxed_arg_match_t arg_match = boxed_arg_match_t();
constexpr
detail
::
on_the_fly_rvalue_builder
on_arg_match
;
template
<
typename
Arg0
,
typename
...
Args
>
detail
::
rvalue_builder
<
typename
detail
::
unboxed
<
typename
util
::
rm_ref
<
Arg0
>::
type
>::
type
,
typename
detail
::
unboxed
<
typename
util
::
rm_ref
<
Args
>::
type
>::
type
...
>
on
(
Arg0
&&
arg0
,
Args
&&
...
args
)
detail
::
rvalue_builder
<
detail
::
value_guard
<
typename
util
::
tl_trim
<
typename
util
::
tl_map
<
util
::
type_list
<
Arg0
,
Args
...
>
,
detail
::
boxed_and_callable_to_void
,
detail
::
implicit_conversions
>::
type
>::
type
>
,
typename
util
::
tl_map
<
util
::
type_list
<
Arg0
,
Args
...
>
,
detail
::
not_callable_to_void
>::
type
,
util
::
type_list
<
typename
detail
::
pattern_type
<
Arg0
>::
type
,
typename
detail
::
pattern_type
<
Args
>::
type
...
>
>
on
(
Arg0
const
&
arg0
,
Args
const
&
...
args
)
{
return
{
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)
...};
return
{
detail
::
rvalue_builder_args_ctor
{},
arg0
,
args
...};
}
template
<
typename
...
TypeList
>
detail
::
rvalue_builder
<
TypeList
...
>
on
()
template
<
typename
...
T
>
detail
::
rvalue_builder
<
detail
::
value_guard
<
util
::
type_list
<>
>
,
util
::
type_list
<>
,
util
::
type_list
<
T
...
>
>
on
()
{
return
{
};
return
{};
}
template
<
atom_value
A0
,
typename
...
Ts
>
de
tail
::
rvalue_builder
<
atom_value
,
Ts
...
>
on
()
de
cltype
(
on
(
A0
,
val
<
Ts
>
()...))
on
()
{
return
{
A0
}
;
return
on
(
A0
,
val
<
Ts
>
()...)
;
}
template
<
atom_value
A0
,
atom_value
A1
,
typename
...
Ts
>
de
tail
::
rvalue_builder
<
atom_value
,
atom_value
,
Ts
...
>
on
()
de
cltype
(
on
(
A0
,
A1
,
val
<
Ts
>
()...))
on
()
{
return
{
A0
,
A1
}
;
return
on
(
A0
,
A1
,
val
<
Ts
>
()...)
;
}
template
<
atom_value
A0
,
atom_value
A1
,
atom_value
A2
,
typename
...
Ts
>
de
tail
::
rvalue_builder
<
atom_value
,
atom_value
,
atom_value
,
Ts
...
>
on
()
de
cltype
(
on
(
A0
,
A1
,
A2
,
val
<
Ts
>
()...))
on
()
{
return
{
A0
,
A1
,
A2
}
;
return
on
(
A0
,
A1
,
A2
,
val
<
Ts
>
()...)
;
}
template
<
atom_value
A0
,
atom_value
A1
,
atom_value
A2
,
atom_value
A3
,
template
<
atom_value
A0
,
atom_value
A1
,
atom_value
A2
,
atom_value
A3
,
typename
...
Ts
>
detail
::
rvalue_builder
<
atom_value
,
atom_value
,
atom_value
,
atom_value
,
Ts
...
>
on
()
decltype
(
on
(
A0
,
A1
,
A2
,
A3
,
val
<
Ts
>
()...))
on
()
{
return
{
A0
,
A1
,
A2
,
A3
}
;
return
on
(
A0
,
A1
,
A2
,
A3
,
val
<
Ts
>
()...)
;
}
template
<
class
Rep
,
class
Period
>
...
...
@@ -363,9 +395,9 @@ after(std::chrono::duration<Rep, Period> const& d)
return
{
util
::
duration
(
d
)
};
}
inline
de
tail
::
rvalue_builder
<
anything
>
others
()
inline
de
cltype
(
on
<
anything
>
())
others
()
{
return
{
}
;
return
on
<
anything
>
()
;
}
#endif
...
...
cppa/partial_function.hpp
View file @
332f9eee
...
...
@@ -55,55 +55,50 @@ class partial_function
public:
typedef
std
::
unique_ptr
<
detail
::
invokable
>
invokable_ptr
;
partial_function
()
=
default
;
partial_function
(
partial_function
&&
other
)
;
partial_function
&
operator
=
(
partial_function
&&
other
)
;
partial_function
(
invokable_ptr
&&
ptr
)
;
struct
impl
{
virtual
~
impl
()
;
virtual
bool
invoke
(
any_tuple
&
)
=
0
;
virtual
bool
invoke
(
any_tuple
const
&
)
=
0
;
virtual
bool
defined_at
(
any_tuple
const
&
)
=
0
;
}
;
bool
defined_at
(
any_tuple
const
&
value
)
;
typedef
std
::
unique_ptr
<
impl
>
impl_ptr
;
bool
operator
()(
any_tuple
value
);
partial_function
()
=
default
;
partial_function
(
partial_function
&&
)
=
default
;
partial_function
&
operator
=
(
partial_function
&&
)
=
default
;
detail
::
invokable
const
*
definition_at
(
any_tuple
value
);
partial_function
(
impl_ptr
&&
ptr
);
template
<
class
...
Args
>
partial_function
&
splice
(
partial_function
&&
arg0
,
Args
&&
...
args
)
inline
bool
defined_at
(
any_tuple
const
&
value
)
{
m_funs
.
splice_after
(
m_funs
.
before_end
(),
std
::
move
(
arg0
.
m_funs
));
arg0
.
m_cache
.
clear
();
return
splice
(
std
::
forward
<
Args
>
(
args
)...);
return
((
m_impl
)
&&
m_impl
->
defined_at
(
value
));
}
private:
inline
bool
operator
()(
any_tuple
&
value
)
{
return
((
m_impl
)
&&
m_impl
->
invoke
(
value
));
}
// terminates recursion
inline
partial_function
&
splice
()
inline
bool
operator
()(
any_tuple
const
&
value
)
{
m_cache
.
clear
();
return
*
this
;
return
((
m_impl
)
&&
m_impl
->
invoke
(
value
));
}
typedef
std
::
vector
<
detail
::
invokable
*>
cache_entry
;
typedef
std
::
pair
<
void
const
*
,
cache_entry
>
cache_element
;
inline
bool
operator
()(
any_tuple
&&
value
)
{
any_tuple
cpy
{
std
::
move
(
value
)};
return
(
*
this
)(
cpy
);
}
intrusive
::
singly_linked_list
<
detail
::
invokable
>
m_funs
;
std
::
vector
<
cache_element
>
m_cache
;
cache_element
m_dummy
;
// binary search dummy
private:
cache_entry
&
get_cache_entry
(
any_tuple
const
&
value
)
;
impl_ptr
m_impl
;
};
inline
partial_function
operator
,(
partial_function
&&
lhs
,
partial_function
&&
rhs
)
{
return
std
::
move
(
lhs
.
splice
(
std
::
move
(
rhs
)));
}
behavior
operator
,(
partial_function
&&
lhs
,
behavior
&&
rhs
);
//behavior operator,(partial_function&& lhs, behavior&& rhs);
}
// namespace cppa
...
...
cppa/primitive_variant.hpp
View file @
332f9eee
...
...
@@ -39,8 +39,6 @@
#include "cppa/primitive_type.hpp"
#include "cppa/util/pt_token.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/pt_dispatch.hpp"
#include "cppa/util/is_primitive.hpp"
...
...
@@ -51,11 +49,11 @@ namespace cppa { namespace detail {
template
<
primitive_type
FT
,
class
T
,
class
V
>
void
ptv_set
(
primitive_type
&
lhs_type
,
T
&
lhs
,
V
&&
rhs
,
typename
util
::
disable_if
<
std
::
is_arithmetic
<
T
>
>::
type
*
=
0
);
typename
std
::
enable_if
<!
std
::
is_arithmetic
<
T
>::
value
>::
type
*
=
0
);
template
<
primitive_type
FT
,
class
T
,
class
V
>
void
ptv_set
(
primitive_type
&
lhs_type
,
T
&
lhs
,
V
&&
rhs
,
typename
util
::
enable_if
<
std
::
is_arithmetic
<
T
>
,
int
>::
type
*
=
0
);
typename
std
::
enable_if
<
std
::
is_arithmetic
<
T
>::
value
,
int
>::
type
*
=
0
);
}
}
// namespace cppa::detail
...
...
@@ -363,7 +361,7 @@ bool operator!=(primitive_variant const& lhs, primitive_variant const& rhs)
}
template
<
typename
T
>
typename
util
::
enable_if
<
util
::
is_primitive
<
T
>
,
bool
>::
type
typename
std
::
enable_if
<
util
::
is_primitive
<
T
>::
value
,
bool
>::
type
operator
==
(
T
const
&
lhs
,
primitive_variant
const
&
rhs
)
{
static
constexpr
primitive_type
ptype
=
detail
::
type_to_ptype
<
T
>::
ptype
;
...
...
@@ -372,21 +370,21 @@ operator==(T const& lhs, primitive_variant const& rhs)
}
template
<
typename
T
>
typename
util
::
enable_if
<
util
::
is_primitive
<
T
>
,
bool
>::
type
typename
std
::
enable_if
<
util
::
is_primitive
<
T
>::
value
,
bool
>::
type
operator
==
(
primitive_variant
const
&
lhs
,
T
const
&
rhs
)
{
return
(
rhs
==
lhs
);
}
template
<
typename
T
>
typename
util
::
enable_if
<
util
::
is_primitive
<
T
>
,
bool
>::
type
typename
std
::
enable_if
<
util
::
is_primitive
<
T
>::
value
,
bool
>::
type
operator
!=
(
primitive_variant
const
&
lhs
,
T
const
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
template
<
typename
T
>
typename
util
::
enable_if
<
util
::
is_primitive
<
T
>
,
bool
>::
type
typename
std
::
enable_if
<
util
::
is_primitive
<
T
>::
value
,
bool
>::
type
operator
!=
(
T
const
&
lhs
,
primitive_variant
const
&
rhs
)
{
return
!
(
lhs
==
rhs
);
...
...
@@ -398,7 +396,7 @@ namespace cppa { namespace detail {
template
<
primitive_type
FT
,
class
T
,
class
V
>
void
ptv_set
(
primitive_type
&
lhs_type
,
T
&
lhs
,
V
&&
rhs
,
typename
util
::
disable_if
<
std
::
is_arithmetic
<
T
>
>::
type
*
)
typename
std
::
enable_if
<!
std
::
is_arithmetic
<
T
>::
value
>::
type
*
)
{
if
(
FT
==
lhs_type
)
{
...
...
@@ -413,7 +411,7 @@ void ptv_set(primitive_type& lhs_type, T& lhs, V&& rhs,
template
<
primitive_type
FT
,
class
T
,
class
V
>
void
ptv_set
(
primitive_type
&
lhs_type
,
T
&
lhs
,
V
&&
rhs
,
typename
util
::
enable_if
<
std
::
is_arithmetic
<
T
>
,
int
>::
type
*
)
typename
std
::
enable_if
<
std
::
is_arithmetic
<
T
>::
value
,
int
>::
type
*
)
{
// don't call a constructor for arithmetic types
lhs
=
rhs
;
...
...
cppa/receive.hpp
View file @
332f9eee
...
...
@@ -121,36 +121,26 @@ inline void receive(behavior& bhvr) { self->dequeue(bhvr); }
inline
void
receive
(
partial_function
&
fun
)
{
self
->
dequeue
(
fun
);
}
inline
void
receive
(
behavior
&&
arg0
)
template
<
typename
Arg0
,
typename
...
Args
>
void
receive
(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
behavior
tmp
{
std
::
move
(
arg0
)};
auto
tmp
=
match_expr_concat
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
receive
(
tmp
);
}
template
<
typename
...
Args
>
void
receive
(
partial_function
&&
arg0
,
Args
&&
...
args
)
{
typename
detail
::
select_bhvr
<
Args
...
>::
type
tmp
;
receive
(
tmp
.
splice
(
std
::
move
(
arg0
),
std
::
forward
<
Args
>
(
args
)...));
}
void
receive_loop
(
behavior
&
rules
);
void
receive_loop
(
partial_function
&
rules
);
inline
void
receive_loop
(
behavior
&&
arg0
)
template
<
typename
Arg0
,
typename
...
Args
>
void
receive_loop
(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
behavior
tmp
{
std
::
move
(
arg0
)};
auto
tmp
=
match_expr_concat
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
receive_loop
(
tmp
);
}
template
<
typename
...
Args
>
void
receive_loop
(
partial_function
&&
arg0
,
Args
&&
...
args
)
{
typename
detail
::
select_bhvr
<
Args
...
>::
type
tmp
;
receive_loop
(
tmp
.
splice
(
std
::
move
(
arg0
),
std
::
forward
<
Args
>
(
args
)...));
}
template
<
typename
T
>
detail
::
receive_for_helper
<
T
>
receive_for
(
T
&
begin
,
T
const
&
end
)
{
...
...
cppa/util/apply_tuple.hpp
View file @
332f9eee
...
...
@@ -31,9 +31,9 @@
#ifndef APPLY_TUPLE_HPP
#define APPLY_TUPLE_HPP
#include <type_traits>
#include "cppa/get.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/is_manipulator.hpp"
#include "cppa/util/callable_trait.hpp"
...
...
cppa/util/disable_if.hpp
deleted
100644 → 0
View file @
d3d55a4c
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef DISABLE_IF_HPP
#define DISABLE_IF_HPP
namespace
cppa
{
namespace
util
{
template
<
bool
Stmt
,
typename
T
=
void
>
struct
disable_if_c
{
};
template
<
typename
T
>
struct
disable_if_c
<
false
,
T
>
{
typedef
T
type
;
};
/**
* @ingroup MetaProgramming
* @brief SFINAE trick to disable a template function based on its
* template parameters.
*/
template
<
class
Trait
,
typename
T
=
void
>
struct
disable_if
:
disable_if_c
<
Trait
::
value
,
T
>
{
};
}
}
// namespace cppa::util
#endif // DISABLE_IF_HPP
cppa/util/is_forward_iterator.hpp
View file @
332f9eee
...
...
@@ -31,9 +31,9 @@
#ifndef IS_FORWARD_ITERATOR_HPP
#define IS_FORWARD_ITERATOR_HPP
#include <type_traits>
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
namespace
cppa
{
namespace
util
{
...
...
@@ -52,11 +52,11 @@ class is_forward_iterator
// check for 'C::value_type C::operator*()' returning a non-void type
typename
rm_ref
<
decltype
(
*
(
*
iter
))
>::
type
*
=
0
,
// check for 'C& C::operator++()'
typename
enable_if
<
std
::
is_same
<
C
&
,
decltype
(
++
(
*
iter
))
>
>::
type
*
=
0
,
typename
std
::
enable_if
<
std
::
is_same
<
C
&
,
decltype
(
++
(
*
iter
))
>::
value
>::
type
*
=
0
,
// check for 'bool C::operator==()'
typename
enable_if
<
std
::
is_same
<
bool
,
decltype
(
*
iter
==
*
iter
)
>
>::
type
*
=
0
,
typename
std
::
enable_if
<
std
::
is_same
<
bool
,
decltype
(
*
iter
==
*
iter
)
>::
value
>::
type
*
=
0
,
// check for 'bool C::operator!=()'
typename
enable_if
<
std
::
is_same
<
bool
,
decltype
(
*
iter
!=
*
iter
)
>
>::
type
*
=
0
typename
std
::
enable_if
<
std
::
is_same
<
bool
,
decltype
(
*
iter
!=
*
iter
)
>::
value
>::
type
*
=
0
)
{
return
true
;
...
...
cppa/util/is_iterable.hpp
View file @
332f9eee
...
...
@@ -51,9 +51,9 @@ class is_iterable
(
C
const
*
cc
,
// check for 'C::begin()' returning a forward iterator
typename
util
::
enable_if
<
util
::
is_forward_iterator
<
decltype
(
cc
->
begin
())
>
>::
type
*
=
0
,
typename
std
::
enable_if
<
util
::
is_forward_iterator
<
decltype
(
cc
->
begin
())
>::
value
>::
type
*
=
0
,
// check for 'C::end()' returning the same kind of forward iterator
typename
util
::
enable_if
<
std
::
is_same
<
decltype
(
cc
->
begin
()),
decltype
(
cc
->
end
())
>
>::
type
*
=
0
typename
std
::
enable_if
<
std
::
is_same
<
decltype
(
cc
->
begin
()),
decltype
(
cc
->
end
())
>::
value
>::
type
*
=
0
)
{
return
true
;
...
...
cppa/util/type_list.hpp
View file @
332f9eee
...
...
@@ -895,9 +895,12 @@ struct tl_pad_left_impl<List, Size, Size, FillType>
template
<
class
List
,
size_t
NewSize
,
typename
FillType
=
void_type
>
struct
tl_pad_left
{
static_assert
(
NewSize
>=
List
::
size
,
"List too big"
);
//
static_assert(NewSize >= List::size, "List too big");
typedef
typename
tl_pad_left_impl
<
List
,
List
::
size
,
NewSize
,
FillType
List
,
List
::
size
,
(
List
::
size
>
NewSize
)
?
List
::
size
:
NewSize
,
FillType
>::
type
type
;
};
...
...
@@ -992,6 +995,18 @@ struct tl_group_by
typedef
typename
tl_group_by_impl
<
List
,
type_list
<>
,
Predicate
>::
type
type
;
};
/**
* @brief Applies the types of the list to @p VarArgTemplate.
*/
template
<
class
List
,
template
<
typename
...
>
class
VarArgTemplate
>
struct
tl_apply
;
template
<
typename
...
Ts
,
template
<
typename
...
>
class
VarArgTemplate
>
struct
tl_apply
<
type_list
<
Ts
...
>
,
VarArgTemplate
>
{
typedef
VarArgTemplate
<
Ts
...
>
type
;
};
/**
* @}
*/
...
...
examples/math_actor_example.cpp
View file @
332f9eee
...
...
@@ -21,7 +21,7 @@ void math_fun()
{
reply
(
atom
(
"result"
),
a
+
b
);
},
on
(
atom
(
"minus"
),
arg_match
)
>>
[](
int
a
,
int
b
)
on
<
atom
(
"minus"
),
int
,
int
>
(
)
>>
[](
int
a
,
int
b
)
{
reply
(
atom
(
"result"
),
a
-
b
);
},
...
...
src/binary_deserializer.cpp
View file @
332f9eee
...
...
@@ -35,10 +35,9 @@
#include <stdexcept>
#include <type_traits>
#include "cppa/util/enable_if.hpp"
#include "cppa/binary_deserializer.hpp"
using
cppa
::
util
::
enable_if
;
using
std
::
enable_if
;
namespace
cppa
{
...
...
@@ -57,14 +56,14 @@ inline void range_check(iterator begin, iterator end, size_t read_size)
// @returns the next iterator position
template
<
typename
T
>
iterator
read
(
iterator
,
iterator
,
T
&
,
typename
enable_if
<
std
::
is_floating_point
<
T
>
>::
type
*
=
0
)
typename
enable_if
<
std
::
is_floating_point
<
T
>::
value
>::
type
*
=
0
)
{
throw
std
::
logic_error
(
"read floating point not implemented yet"
);
}
template
<
typename
T
>
iterator
read
(
iterator
begin
,
iterator
end
,
T
&
storage
,
typename
enable_if
<
std
::
is_integral
<
T
>
>::
type
*
=
0
)
typename
enable_if
<
std
::
is_integral
<
T
>::
value
>::
type
*
=
0
)
{
range_check
(
begin
,
end
,
sizeof
(
T
));
memcpy
(
&
storage
,
begin
,
sizeof
(
T
));
...
...
src/binary_serializer.cpp
View file @
332f9eee
...
...
@@ -33,11 +33,10 @@
#include <cstdint>
#include <type_traits>
#include "cppa/util/enable_if.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/binary_serializer.hpp"
using
cppa
::
util
::
enable_if
;
using
std
::
enable_if
;
namespace
{
...
...
@@ -75,7 +74,7 @@ class binary_writer
template
<
typename
T
>
void
operator
()(
const
T
&
value
,
typename
enable_if
<
std
::
is_integral
<
T
>
>::
type
*
=
0
)
typename
enable_if
<
std
::
is_integral
<
T
>::
value
>::
type
*
=
0
)
{
m_serializer
->
acquire
(
sizeof
(
T
));
write_int
(
m_serializer
,
value
);
...
...
@@ -83,7 +82,7 @@ class binary_writer
template
<
typename
T
>
void
operator
()(
const
T
&
,
typename
enable_if
<
std
::
is_floating_point
<
T
>
>::
type
*
=
0
)
typename
enable_if
<
std
::
is_floating_point
<
T
>::
value
>::
type
*
=
0
)
{
throw
std
::
logic_error
(
"binary_serializer::write_floating_point "
"not implemented yet"
);
...
...
src/partial_function.cpp
View file @
332f9eee
...
...
@@ -37,101 +37,12 @@
namespace
cppa
{
partial_function
::
partial_function
(
i
nvokable_ptr
&&
ptr
)
partial_function
::
partial_function
(
i
mpl_ptr
&&
ptr
)
:
m_impl
(
std
::
move
(
ptr
)
)
{
m_funs
.
push_back
(
ptr
.
release
());
}
partial_function
::
partial_function
(
partial_function
&&
other
)
:
m_funs
(
std
::
move
(
other
.
m_funs
))
partial_function
::
impl
::~
impl
()
{
}
partial_function
&
partial_function
::
operator
=
(
partial_function
&&
other
)
{
m_funs
=
std
::
move
(
other
.
m_funs
);
m_cache
.
clear
();
return
*
this
;
}
auto
partial_function
::
get_cache_entry
(
any_tuple
const
&
value
)
->
cache_entry
&
{
m_dummy
.
first
=
value
.
type_token
();
auto
end
=
m_cache
.
end
();
// note: uses >= for comparison (not a "real" upper bound)
auto
i
=
std
::
upper_bound
(
m_cache
.
begin
(),
end
,
m_dummy
,
[](
cache_element
const
&
lhs
,
cache_element
const
&
rhs
)
{
return
lhs
.
first
>=
rhs
.
first
;
});
// if we didn't found a cache entry ...
if
(
i
==
end
||
i
->
first
!=
m_dummy
.
first
)
{
// ... create one
cache_entry
tmp
;
if
(
value
.
impl_type
()
==
detail
::
tuple_impl_info
::
statically_typed
)
{
// use static type information for optimal caching
for
(
auto
f
=
m_funs
.
begin
();
f
!=
m_funs
.
end
();
++
f
)
{
if
(
f
->
types_match
(
value
))
tmp
.
push_back
(
f
.
ptr
());
}
}
else
{
// "dummy" cache entry with all functions (dynamically typed tuple)
for
(
auto
f
=
m_funs
.
begin
();
f
!=
m_funs
.
end
();
++
f
)
{
tmp
.
push_back
(
f
.
ptr
());
}
}
// m_cache is always sorted,
// due to emplace(upper_bound, ...) insertions
i
=
m_cache
.
emplace
(
i
,
std
::
move
(
m_dummy
.
first
),
std
::
move
(
tmp
));
}
return
i
->
second
;
}
bool
partial_function
::
operator
()(
any_tuple
value
)
{
using
detail
::
invokable
;
auto
&
v
=
get_cache_entry
(
value
);
if
(
value
.
impl_type
()
==
detail
::
tuple_impl_info
::
statically_typed
)
{
return
std
::
any_of
(
v
.
begin
(),
v
.
end
(),
[
&
](
invokable
*
i
)
{
return
i
->
unsafe_invoke
(
value
);
});
}
else
{
return
std
::
any_of
(
v
.
begin
(),
v
.
end
(),
[
&
](
invokable
*
i
)
{
return
i
->
invoke
(
value
);
});
}
}
detail
::
invokable
const
*
partial_function
::
definition_at
(
any_tuple
value
)
{
using
detail
::
invokable
;
auto
&
v
=
get_cache_entry
(
value
);
auto
i
=
(
value
.
impl_type
()
==
detail
::
tuple_impl_info
::
statically_typed
)
?
std
::
find_if
(
v
.
begin
(),
v
.
end
(),
[
&
](
invokable
*
i
)
{
return
i
->
could_invoke
(
value
);})
:
std
::
find_if
(
v
.
begin
(),
v
.
end
(),
[
&
](
invokable
*
i
)
{
return
i
->
invoke
(
value
);
});
return
(
i
!=
v
.
end
())
?
*
i
:
nullptr
;
}
bool
partial_function
::
defined_at
(
any_tuple
const
&
value
)
{
return
definition_at
(
value
)
!=
nullptr
;
}
behavior
operator
,(
partial_function
&&
lhs
,
behavior
&&
rhs
)
{
behavior
bhvr
{
rhs
.
m_timeout
,
std
::
move
(
rhs
.
m_timeout_handler
)};
bhvr
.
get_partial_function
().
splice
(
std
::
move
(
rhs
.
get_partial_function
()),
std
::
move
(
lhs
));
return
bhvr
;
}
}
// namespace cppa
src/primitive_variant.cpp
View file @
332f9eee
...
...
@@ -39,14 +39,14 @@ namespace {
template
<
class
T
>
void
ptv_del
(
T
&
,
typename
util
::
enable_if
<
std
::
is_arithmetic
<
T
>
,
int
>::
type
*
=
0
)
typename
std
::
enable_if
<
std
::
is_arithmetic
<
T
>::
value
>::
type
*
=
0
)
{
// arithmetic types don't need destruction
}
template
<
class
T
>
void
ptv_del
(
T
&
what
,
typename
util
::
disable_if
<
std
::
is_arithmetic
<
T
>
>::
type
*
=
0
)
typename
std
::
enable_if
<!
std
::
is_arithmetic
<
T
>::
value
>::
type
*
=
0
)
{
what
.
~
T
();
}
...
...
src/scheduler.cpp
View file @
332f9eee
...
...
@@ -123,6 +123,15 @@ void scheduler_helper::time_emitter(scheduler_helper::ptr_type m_self)
on
<
atom
(
":_DIE"
)
>
()
>>
[
&
]()
{
done
=
true
;
},
others
()
>>
[
&
]()
{
# ifdef CPPA_DEBUG
std
::
cerr
<<
"scheduler_helper::time_emitter: UNKNOWN MESSAGE: "
<<
to_string
(
msg_ptr
->
msg
)
<<
std
::
endl
;
# endif
msg_ptr
.
reset
();
}
);
// loop
...
...
src/uniform_type_info.cpp
View file @
332f9eee
...
...
@@ -53,8 +53,6 @@
#include "cppa/util/duration.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/detail/demangle.hpp"
#include "cppa/detail/object_array.hpp"
...
...
@@ -639,8 +637,7 @@ class int_tinfo : public detail::default_uniform_type_info_impl<T>
};
using
std
::
is_integral
;
using
util
::
enable_if
;
using
util
::
disable_if
;
using
std
::
enable_if
;
class
uniform_type_info_map_helper
{
...
...
@@ -664,7 +661,7 @@ class uniform_type_info_map_helper
template
<
typename
T
>
static
inline
void
insert
(
this_ptr
d
,
std
::
set
<
std
::
string
>
const
&
tnames
,
typename
enable_if
<
is_integral
<
T
>>::
type
*
=
0
)
typename
enable_if
<
is_integral
<
T
>
::
value
>::
type
*
=
0
)
{
insert
(
d
,
new
int_tinfo
<
T
>
,
tnames
);
}
...
...
@@ -672,7 +669,7 @@ class uniform_type_info_map_helper
template
<
typename
T
>
static
inline
void
insert
(
this_ptr
d
,
std
::
set
<
std
::
string
>
const
&
tnames
,
typename
disable_if
<
is_integral
<
T
>
>::
type
*
=
0
)
typename
enable_if
<!
is_integral
<
T
>::
value
>::
type
*
=
0
)
{
insert
(
d
,
new
default_uniform_type_info_impl
<
T
>
(),
tnames
);
}
...
...
unit_testing/main.cpp
View file @
332f9eee
...
...
@@ -148,7 +148,7 @@ int main(int argc, char** argv)
auto
args
=
get_kv_pairs
(
argc
,
argv
);
match_each
(
args
)
(
on
(
"run"
,
arg_match
)
>>
[
&
](
std
::
string
const
&
what
)
on
(
"run"
,
val
<
std
::
string
>
)
>>
[
&
](
std
::
string
const
&
what
)
{
if
(
what
==
"remote_actor"
)
{
...
...
@@ -156,7 +156,7 @@ int main(int argc, char** argv)
exit
(
0
);
}
},
on
(
"scheduler"
,
arg_match
)
>>
[](
std
::
string
const
&
sched
)
on
(
"scheduler"
,
val
<
std
::
string
>
)
>>
[](
std
::
string
const
&
sched
)
{
if
(
sched
==
"thread_pool_scheduler"
)
{
...
...
unit_testing/test.hpp
View file @
332f9eee
...
...
@@ -8,19 +8,22 @@
#include <iostream>
#include <type_traits>
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
template
<
typename
T1
,
typename
T2
>
inline
bool
cppa_check_value_fun_eq
(
T1
const
&
value1
,
T2
const
&
value2
,
typename
cppa
::
util
::
disable_if_c
<
std
::
is_integral
<
T1
>::
value
&&
std
::
is_integral
<
T2
>::
value
>::
type
*
=
0
)
typename
std
::
enable_if
<
!
std
::
is_integral
<
T1
>::
value
||
!
std
::
is_integral
<
T2
>::
value
>::
type
*
=
0
)
{
return
value1
==
value2
;
}
template
<
typename
T1
,
typename
T2
>
inline
bool
cppa_check_value_fun_eq
(
T1
value1
,
T2
value2
,
typename
cppa
::
util
::
enable_if_c
<
std
::
is_integral
<
T1
>::
value
&&
std
::
is_integral
<
T2
>::
value
>::
type
*
=
0
)
typename
std
::
enable_if
<
std
::
is_integral
<
T1
>::
value
&&
std
::
is_integral
<
T2
>::
value
>::
type
*
=
0
)
{
return
value1
==
static_cast
<
T1
>
(
value2
);
}
...
...
unit_testing/test__match.cpp
View file @
332f9eee
...
...
@@ -175,7 +175,7 @@ size_t test__match()
vector
<
string
>
vec
{
"a"
,
"b"
,
"c"
};
match
(
vec
)
(
on
(
"a"
,
"b"
,
arg_match
)
>>
[
&
](
string
&
str
)
on
(
"a"
,
"b"
,
val
<
string
>
)
>>
[
&
](
string
&
str
)
{
invoked
=
true
;
str
=
"C"
;
...
...
@@ -197,6 +197,7 @@ size_t test__match()
CPPA_CHECK_EQUAL
(
"A"
,
vec
.
front
());
invoked
=
false
;
/*
match(vec)
(
others() >> [&](any_tuple& tup)
...
...
@@ -214,7 +215,7 @@ size_t test__match()
);
if (!invoked) { CPPA_ERROR("match({\"a\", \"b\", \"c\"}) failed"); }
CPPA_CHECK_EQUAL(vec[1], "B");
invoked
=
false
;
*/
vector
<
string
>
vec2
{
"a=0"
,
"b=1"
,
"c=2"
};
...
...
@@ -226,34 +227,36 @@ size_t test__match()
CPPA_CHECK_EQUAL
(
true
,
invoked
);
invoked
=
false
;
/*,
int pmatches = 0;
using std::placeholders::_1;
pmatch_each(vec2.begin(), vec2.end(), std::bind(split, _1, '='))
(
on
(
"a"
,
arg_match
)
>>
[
&
](
string
const
&
value
)
on("a",
val<string>
) >> [&](string const& value)
{
CPPA_CHECK_EQUAL("0", value);
CPPA_CHECK_EQUAL(0, pmatches);
++pmatches;
},
on
(
"b"
,
arg_match
)
>>
[
&
](
string
const
&
value
)
on("b",
val<string>
) >> [&](string const& value)
{
CPPA_CHECK_EQUAL("1", value);
CPPA_CHECK_EQUAL(1, pmatches);
++pmatches;
},
on
(
"c"
,
arg_match
)
>>
[
&
](
string
const
&
value
)
on("c",
val<string>
) >> [&](string const& value)
{
CPPA_CHECK_EQUAL("2", value);
CPPA_CHECK_EQUAL(2, pmatches);
++pmatches;
}
,
}
others() >> [](any_tuple const& value)
{
cout << to_string(value) << endl;
}
);
CPPA_CHECK_EQUAL(3, pmatches);
*/
return
CPPA_TEST_RESULT
;
}
unit_testing/test__pattern.cpp
View file @
332f9eee
...
...
@@ -14,8 +14,6 @@
#include "cppa/tuple_cast.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/apply_tuple.hpp"
#include "cppa/util/is_primitive.hpp"
#include "cppa/util/is_mutable_ref.hpp"
...
...
unit_testing/test__serialization.cpp
View file @
332f9eee
...
...
@@ -41,8 +41,6 @@
#include "cppa/binary_deserializer.hpp"
#include "cppa/util/pt_token.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/is_iterable.hpp"
#include "cppa/util/is_primitive.hpp"
#include "cppa/util/abstract_uniform_type_info.hpp"
...
...
unit_testing/test__spawn.cpp
View file @
332f9eee
...
...
@@ -330,6 +330,11 @@ size_t test__spawn()
{
CPPA_TEST
(
test__spawn
);
CPPA_IF_VERBOSE
(
cout
<<
"test send() ... "
<<
std
::
flush
);
send
(
self
,
1
,
2
,
3
);
receive
(
on
(
1
,
2
,
3
)
>>
[]()
{
});
CPPA_IF_VERBOSE
(
cout
<<
"ok"
<<
endl
);
CPPA_IF_VERBOSE
(
cout
<<
"test future_send() ... "
<<
std
::
flush
);
future_send
(
self
,
std
::
chrono
::
seconds
(
1
),
1
,
2
,
3
);
receive
(
on
(
1
,
2
,
3
)
>>
[]()
{
});
...
...
unit_testing/test__tuple.cpp
View file @
332f9eee
#include <list>
#include <array>
#include <string>
#include <limits>
#include <cstdint>
#include <utility>
#include <iostream>
#include <typeinfo>
...
...
@@ -38,1042 +40,11 @@ using std::endl;
using
namespace
cppa
;
using
namespace
cppa
::
detail
;
template
<
typename
...
T
>
struct
pseudo_tuple
{
typedef
void
*
ptr_type
;
typedef
void
const
*
const_ptr_type
;
ptr_type
data
[
sizeof
...(
T
)
>
0
?
sizeof
...(
T
)
:
1
];
inline
const_ptr_type
at
(
size_t
p
)
const
{
return
data
[
p
];
}
inline
ptr_type
mutable_at
(
size_t
p
)
{
return
const_cast
<
ptr_type
>
(
data
[
p
]);
}
inline
void
*&
operator
[](
size_t
p
)
{
return
data
[
p
];
}
};
template
<
class
List
>
struct
pseudo_tuple_from_type_list
;
template
<
typename
...
Ts
>
struct
pseudo_tuple_from_type_list
<
util
::
type_list
<
Ts
...
>
>
{
typedef
pseudo_tuple
<
Ts
...
>
type
;
};
template
<
size_t
N
,
typename
...
Tn
>
typename
util
::
at
<
N
,
Tn
...
>::
type
const
&
get
(
pseudo_tuple
<
Tn
...
>
const
&
tv
)
{
static_assert
(
N
<
sizeof
...(
Tn
),
"N >= tv.size()"
);
return
*
reinterpret_cast
<
typename
util
::
at
<
N
,
Tn
...
>::
type
const
*>
(
tv
.
at
(
N
));
}
template
<
size_t
N
,
typename
...
Tn
>
typename
util
::
at
<
N
,
Tn
...
>::
type
&
get_ref
(
pseudo_tuple
<
Tn
...
>&
tv
)
{
static_assert
(
N
<
sizeof
...(
Tn
),
"N >= tv.size()"
);
return
*
reinterpret_cast
<
typename
util
::
at
<
N
,
Tn
...
>::
type
*>
(
tv
.
mutable_at
(
N
));
}
// covers wildcard_position::multiple and wildcard_position::in_between
template
<
wildcard_position
,
class
Pattern
,
class
FilteredPattern
>
struct
invoke_policy_impl
{
typedef
FilteredPattern
filtered_pattern
;
template
<
class
Tuple
>
static
bool
can_invoke
(
std
::
type_info
const
&
type_token
,
Tuple
const
&
tup
)
{
typedef
typename
match_impl_from_type_list
<
Tuple
,
Pattern
>::
type
mimpl
;
return
type_token
==
typeid
(
filtered_pattern
)
||
mimpl
::
_
(
tup
);
}
template
<
class
Target
,
typename
PtrType
,
class
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
type_token
,
detail
::
tuple_impl_info
,
PtrType
*
,
Tuple
&
tup
)
{
typedef
typename
match_impl_from_type_list
<
typename
std
::
remove_const
<
Tuple
>::
type
,
Pattern
>::
type
mimpl
;
util
::
fixed_vector
<
size_t
,
filtered_pattern
::
size
>
mv
;
if
(
type_token
==
typeid
(
filtered_pattern
)
||
mimpl
::
_
(
tup
,
mv
))
{
typedef
typename
pseudo_tuple_from_type_list
<
filtered_pattern
>::
type
ttup_type
;
ttup_type
ttup
;
// if we strip const here ...
for
(
size_t
i
=
0
;
i
<
filtered_pattern
::
size
;
++
i
)
{
ttup
[
i
]
=
const_cast
<
void
*>
(
tup
.
at
(
mv
[
i
]));
}
// ... we restore it here again
typedef
typename
util
::
if_else
<
std
::
is_const
<
Tuple
>
,
ttup_type
const
&
,
util
::
wrapped
<
ttup_type
&>
>::
type
ttup_ref
;
ttup_ref
ttup_fwd
=
ttup
;
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
ttup_fwd
);
}
return
false
;
}
};
template
<
class
Pattern
,
typename
...
Ts
>
struct
invoke_policy_impl
<
wildcard_position
::
nil
,
Pattern
,
util
::
type_list
<
Ts
...
>
>
{
typedef
util
::
type_list
<
Ts
...
>
filtered_pattern
;
typedef
detail
::
tdata
<
Ts
...
>
native_data_type
;
typedef
typename
detail
::
static_types_array
<
Ts
...
>
arr_type
;
template
<
class
Target
,
class
Tup
>
static
bool
invoke
(
std
::
integral_constant
<
bool
,
false
>
,
Target
&
,
Tup
&
)
{
return
false
;
}
template
<
class
Target
,
class
Tup
>
static
bool
invoke
(
std
::
integral_constant
<
bool
,
true
>
,
Target
&
target
,
Tup
&
tup
)
{
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
tup
);
}
template
<
class
Target
,
typename
PtrType
,
class
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
,
detail
::
tuple_impl_info
,
PtrType
*
,
Tuple
&
tup
,
typename
util
::
disable_if
<
std
::
is_same
<
typename
std
::
remove_const
<
Tuple
>::
type
,
detail
::
abstract_tuple
>
>::
type
*
=
0
)
{
static
constexpr
bool
can_apply
=
util
::
tl_binary_forall
<
typename
util
::
tl_map
<
typename
Tuple
::
types
,
util
::
purge_refs
>::
type
,
filtered_pattern
,
std
::
is_same
>::
value
;
return
invoke
(
std
::
integral_constant
<
bool
,
can_apply
>
{},
target
,
tup
);
}
template
<
class
Target
,
typename
PtrType
,
typename
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
arg_types
,
detail
::
tuple_impl_info
timpl
,
PtrType
*
native_arg
,
Tuple
&
tup
,
typename
util
::
enable_if
<
std
::
is_same
<
typename
std
::
remove_const
<
Tuple
>::
type
,
detail
::
abstract_tuple
>
>::
type
*
=
0
)
{
if
(
arg_types
==
typeid
(
filtered_pattern
))
{
if
(
native_arg
)
{
typedef
typename
util
::
if_else_c
<
std
::
is_const
<
PtrType
>::
value
,
native_data_type
const
*
,
util
::
wrapped
<
native_data_type
*>
>::
type
cast_type
;
auto
arg
=
reinterpret_cast
<
cast_type
>
(
native_arg
);
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
*
arg
);
}
// 'fall through'
}
else
if
(
timpl
==
detail
::
dynamically_typed
)
{
auto
&
arr
=
arr_type
::
arr
;
if
(
tup
.
size
()
!=
filtered_pattern
::
size
)
{
return
false
;
}
for
(
size_t
i
=
0
;
i
<
filtered_pattern
::
size
;
++
i
)
{
if
(
arr
[
i
]
!=
tup
.
type_at
(
i
))
{
return
false
;
}
}
// 'fall through'
}
else
{
return
false
;
}
typedef
pseudo_tuple
<
Ts
...
>
ttup_type
;
ttup_type
ttup
;
// if we strip const here ...
for
(
size_t
i
=
0
;
i
<
sizeof
...(
Ts
);
++
i
)
ttup
[
i
]
=
const_cast
<
void
*>
(
tup
.
at
(
i
));
// ... we restore it here again
typedef
typename
util
::
if_else
<
std
::
is_const
<
PtrType
>
,
ttup_type
const
&
,
util
::
wrapped
<
ttup_type
&>
>::
type
ttup_ref
;
ttup_ref
ttup_fwd
=
ttup
;
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
ttup_fwd
);
}
template
<
class
Tuple
>
static
bool
can_invoke
(
std
::
type_info
const
&
arg_types
,
Tuple
const
&
)
{
return
arg_types
==
typeid
(
filtered_pattern
);
}
};
template
<
>
struct
invoke_policy_impl
<
wildcard_position
::
leading
,
util
::
type_list
<
anything
>
,
util
::
type_list
<>
>
{
template
<
class
Tuple
>
static
inline
bool
can_invoke
(
std
::
type_info
const
&
,
Tuple
const
&
)
{
return
true
;
}
template
<
class
Target
,
typename
...
Args
>
static
bool
invoke
(
Target
&
target
,
Args
&&
...)
{
return
target
();
}
};
template
<
class
Pattern
,
typename
...
Ts
>
struct
invoke_policy_impl
<
wildcard_position
::
trailing
,
Pattern
,
util
::
type_list
<
Ts
...
>
>
{
typedef
util
::
type_list
<
Ts
...
>
filtered_pattern
;
template
<
class
Tuple
>
static
bool
can_invoke
(
std
::
type_info
const
&
arg_types
,
Tuple
const
&
tup
)
{
if
(
arg_types
==
typeid
(
filtered_pattern
))
{
return
true
;
}
typedef
detail
::
static_types_array
<
Ts
...
>
arr_type
;
auto
&
arr
=
arr_type
::
arr
;
if
(
tup
.
size
()
<
filtered_pattern
::
size
)
{
return
false
;
}
for
(
size_t
i
=
0
;
i
<
filtered_pattern
::
size
;
++
i
)
{
if
(
arr
[
i
]
!=
tup
.
type_at
(
i
))
{
return
false
;
}
}
return
true
;
}
template
<
class
Target
,
typename
PtrType
,
class
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
arg_types
,
detail
::
tuple_impl_info
,
PtrType
*
,
Tuple
&
tup
)
{
if
(
!
can_invoke
(
arg_types
,
tup
))
return
false
;
typedef
pseudo_tuple
<
Ts
...
>
ttup_type
;
ttup_type
ttup
;
for
(
size_t
i
=
0
;
i
<
sizeof
...(
Ts
);
++
i
)
ttup
[
i
]
=
const_cast
<
void
*>
(
tup
.
at
(
i
));
// ensure const-correctness
typedef
typename
util
::
if_else
<
std
::
is_const
<
Tuple
>
,
ttup_type
const
&
,
util
::
wrapped
<
ttup_type
&>
>::
type
ttup_ref
;
ttup_ref
ttup_fwd
=
ttup
;
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
ttup_fwd
);
}
};
template
<
class
Pattern
,
typename
...
Ts
>
struct
invoke_policy_impl
<
wildcard_position
::
leading
,
Pattern
,
util
::
type_list
<
Ts
...
>
>
{
typedef
util
::
type_list
<
Ts
...
>
filtered_pattern
;
template
<
class
Tuple
>
static
bool
can_invoke
(
std
::
type_info
const
&
arg_types
,
Tuple
const
&
tup
)
{
if
(
arg_types
==
typeid
(
filtered_pattern
))
{
return
true
;
}
typedef
detail
::
static_types_array
<
Ts
...
>
arr_type
;
auto
&
arr
=
arr_type
::
arr
;
if
(
tup
.
size
()
<
filtered_pattern
::
size
)
{
return
false
;
}
size_t
i
=
tup
.
size
()
-
filtered_pattern
::
size
;
size_t
j
=
0
;
while
(
j
<
filtered_pattern
::
size
)
{
if
(
arr
[
i
++
]
!=
tup
.
type_at
(
j
++
))
{
return
false
;
}
}
return
true
;
}
template
<
class
Target
,
typename
PtrType
,
class
Tuple
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
arg_types
,
detail
::
tuple_impl_info
,
PtrType
*
,
Tuple
&
tup
)
{
if
(
!
can_invoke
(
arg_types
,
tup
))
return
false
;
typedef
pseudo_tuple
<
Ts
...
>
ttup_type
;
ttup_type
ttup
;
size_t
i
=
tup
.
size
()
-
filtered_pattern
::
size
;
size_t
j
=
0
;
while
(
j
<
filtered_pattern
::
size
)
{
ttup
[
j
++
]
=
const_cast
<
void
*>
(
tup
.
at
(
i
++
));
}
// ensure const-correctness
typedef
typename
util
::
if_else
<
std
::
is_const
<
Tuple
>
,
ttup_type
const
&
,
util
::
wrapped
<
ttup_type
&>
>::
type
ttup_ref
;
ttup_ref
ttup_fwd
=
ttup
;
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
ttup_fwd
);
}
};
template
<
class
Pattern
>
struct
invoke_policy
:
invoke_policy_impl
<
get_wildcard_position
<
Pattern
>
(),
Pattern
,
typename
util
::
tl_filter_not_type
<
Pattern
,
anything
>::
type
>
{
};
template
<
class
Pattern
,
class
Projection
,
class
PartialFunction
>
struct
projection_partial_function_pair
:
std
::
pair
<
Projection
,
PartialFunction
>
{
template
<
typename
...
Args
>
projection_partial_function_pair
(
Args
&&
...
args
)
:
std
::
pair
<
Projection
,
PartialFunction
>
(
std
::
forward
<
Args
>
(
args
)...)
{
}
typedef
Pattern
pattern_type
;
};
template
<
class
Expr
,
class
Guard
,
class
Transformers
,
class
Pattern
>
struct
get_cfl
{
typedef
typename
util
::
get_callable_trait
<
Expr
>::
type
ctrait
;
typedef
typename
util
::
tl_filter_not_type
<
Pattern
,
anything
>::
type
filtered_pattern
;
typedef
typename
util
::
tl_pad_right
<
Transformers
,
filtered_pattern
::
size
>::
type
padded_transformers
;
typedef
typename
util
::
tl_map
<
filtered_pattern
,
std
::
add_const
,
std
::
add_lvalue_reference
>::
type
base_signature
;
typedef
typename
util
::
tl_map_conditional
<
typename
util
::
tl_pad_left
<
typename
ctrait
::
arg_types
,
filtered_pattern
::
size
>::
type
,
std
::
is_lvalue_reference
,
false
,
std
::
add_const
,
std
::
add_lvalue_reference
>::
type
padded_expr_args
;
// override base signature with required argument types of Expr
// and result types of transformation
typedef
typename
util
::
tl_zip
<
typename
util
::
tl_map
<
padded_transformers
,
util
::
get_result_type
,
util
::
rm_option
,
std
::
add_lvalue_reference
>::
type
,
typename
util
::
tl_zip
<
padded_expr_args
,
base_signature
,
util
::
left_or_right
>::
type
,
util
::
left_or_right
>::
type
partial_fun_signature
;
// 'inherit' mutable references from partial_fun_signature
// for arguments without transformation
typedef
typename
util
::
tl_zip
<
typename
util
::
tl_zip
<
padded_transformers
,
partial_fun_signature
,
util
::
if_not_left
>::
type
,
base_signature
,
util
::
deduce_ref_type
>::
type
projection_signature
;
typedef
typename
projection_from_type_list
<
padded_transformers
,
projection_signature
>::
type
type1
;
typedef
typename
get_tpartial_function
<
Expr
,
Guard
,
partial_fun_signature
>::
type
type2
;
typedef
projection_partial_function_pair
<
Pattern
,
type1
,
type2
>
type
;
};
template
<
typename
First
,
typename
Second
>
struct
pjf_same_pattern
:
std
::
is_same
<
typename
First
::
second
::
pattern_type
,
typename
Second
::
second
::
pattern_type
>
{
};
// last invocation step; evaluates a {projection, tpartial_function} pair
template
<
typename
Data
>
struct
invoke_helper3
{
Data
const
&
data
;
invoke_helper3
(
Data
const
&
mdata
)
:
data
(
mdata
)
{
}
template
<
size_t
Pos
,
typename
T
,
typename
...
Args
>
inline
bool
operator
()(
util
::
type_pair
<
std
::
integral_constant
<
size_t
,
Pos
>
,
T
>
,
Args
&&
...
args
)
const
{
auto
const
&
target
=
get
<
Pos
>
(
data
);
return
target
.
first
(
target
.
second
,
std
::
forward
<
Args
>
(
args
)...);
//return (get<Pos>(data))(args...);
}
};
template
<
class
Data
,
class
Token
,
class
Pattern
>
struct
invoke_helper2
{
typedef
Pattern
pattern_type
;
typedef
typename
util
::
tl_filter_not_type
<
pattern_type
,
anything
>::
type
arg_types
;
Data
const
&
data
;
invoke_helper2
(
Data
const
&
mdata
)
:
data
(
mdata
)
{
}
template
<
typename
...
Args
>
bool
invoke
(
Args
&&
...
args
)
const
{
typedef
invoke_policy
<
Pattern
>
impl
;
return
impl
::
invoke
(
*
this
,
std
::
forward
<
Args
>
(
args
)...);
}
// resolved argument list (called from invoke_policy)
template
<
typename
...
Args
>
bool
operator
()(
Args
&&
...
args
)
const
{
//static_assert(false, "foo");
Token
token
;
invoke_helper3
<
Data
>
fun
{
data
};
return
util
::
static_foreach
<
0
,
Token
::
size
>::
eval_or
(
token
,
fun
,
std
::
forward
<
Args
>
(
args
)...);
}
};
// invokes a group of {projection, tpartial_function} pairs
template
<
typename
Data
,
typename
BoolIter
>
struct
invoke_helper
{
Data
const
&
data
;
BoolIter
enabled
;
invoke_helper
(
Data
const
&
mdata
,
BoolIter
biter
)
:
data
(
mdata
),
enabled
(
biter
)
{
}
// token: type_list<type_pair<integral_constant<size_t, X>,
// std::pair<projection, tpartial_function>>,
// ...>
// all {projection, tpartial_function} pairs have the same pattern
// thus, can be invoked from same data
template
<
class
Token
,
typename
...
Args
>
bool
operator
()(
Token
,
Args
&&
...
args
)
{
typedef
typename
Token
::
head
type_pair
;
typedef
typename
type_pair
::
second
leaf_pair
;
if
(
*
enabled
++
)
{
// next invocation step
invoke_helper2
<
Data
,
Token
,
typename
leaf_pair
::
pattern_type
>
fun
{
data
};
return
fun
.
invoke
(
std
::
forward
<
Args
>
(
args
)...);
}
//++enabled;
return
false
;
}
};
template
<
typename
BoolArray
>
struct
can_invoke_helper
{
BoolArray
&
data
;
size_t
i
;
can_invoke_helper
(
BoolArray
&
mdata
)
:
data
(
mdata
),
i
(
0
)
{
}
template
<
class
Token
,
typename
...
Args
>
void
operator
()(
Token
,
Args
&&
...
args
)
{
typedef
typename
Token
::
head
type_pair
;
typedef
typename
type_pair
::
second
leaf_pair
;
typedef
invoke_policy
<
typename
leaf_pair
::
pattern_type
>
impl
;
data
[
i
++
]
=
impl
::
can_invoke
(
std
::
forward
<
Args
>
(
args
)...);
}
};
template
<
typename
T
>
struct
is_manipulator_leaf
{
static
constexpr
bool
value
=
T
::
second_type
::
manipulates_args
;
};
template
<
bool
IsManipulator
,
typename
T0
,
typename
T1
>
struct
pj_fwd_
{
typedef
T1
type
;
};
template
<
typename
T
>
struct
pj_fwd_
<
false
,
T
const
&
,
T
>
{
typedef
std
::
reference_wrapper
<
const
T
>
type
;
};
template
<
typename
T
>
struct
pj_fwd_
<
true
,
T
&
,
T
>
{
typedef
std
::
reference_wrapper
<
T
>
type
;
};
template
<
bool
IsManipulator
,
typename
T
>
struct
pj_fwd
{
typedef
typename
pj_fwd_
<
IsManipulator
,
T
,
typename
detail
::
implicit_conversions
<
typename
util
::
rm_ref
<
T
>::
type
>::
type
>::
type
type
;
};
/**
* @brief A function that works on the projection of given data rather than
* on the data itself.
*/
template
<
class
...
Leaves
>
class
projected_fun
{
public:
typedef
util
::
type_list
<
Leaves
...
>
leaves_list
;
typedef
typename
util
::
tl_zip_with_index
<
leaves_list
>::
type
zipped_list
;
typedef
typename
util
::
tl_group_by
<
zipped_list
,
pjf_same_pattern
>::
type
eval_order
;
static
constexpr
bool
has_manipulator
=
util
::
tl_exists
<
leaves_list
,
is_manipulator_leaf
>::
value
;
template
<
typename
...
Args
>
projected_fun
(
Args
&&
...
args
)
:
m_leaves
(
std
::
forward
<
Args
>
(
args
)...)
{
init
();
}
projected_fun
(
projected_fun
&&
other
)
:
m_leaves
(
std
::
move
(
other
.
m_leaves
))
{
init
();
}
projected_fun
(
projected_fun
const
&
other
)
:
m_leaves
(
other
.
m_leaves
)
{
init
();
}
bool
invoke
(
any_tuple
const
&
tup
)
{
return
_invoke
(
tup
);
}
bool
invoke
(
any_tuple
&
tup
)
{
return
_invoke
(
tup
);
}
bool
invoke
(
any_tuple
&&
tup
)
{
any_tuple
tmp
{
tup
};
return
invoke
(
tmp
);
}
template
<
typename
...
Args
>
bool
can_invoke
(
Args
&&
...
args
)
{
typedef
detail
::
tdata
<
typename
pj_fwd
<
has_manipulator
,
Args
>::
type
...
>
tuple_type
;
// applies implicit conversions etc
tuple_type
tup
{
std
::
forward
<
Args
>
(
args
)...};
auto
&
type_token
=
typeid
(
typename
tuple_type
::
types
);
eval_order
token
;
cache_entry
tmp
;
can_invoke_helper
<
cache_entry
>
fun
{
tmp
};
util
::
static_foreach
<
0
,
eval_order
::
size
>
::
_
(
token
,
fun
,
type_token
,
tup
);
return
std
::
any_of
(
tmp
.
begin
(),
tmp
.
end
(),
[](
bool
value
)
{
return
value
;
});
}
template
<
typename
...
Args
>
bool
operator
()(
Args
&&
...
args
)
{
typedef
detail
::
tdata
<
typename
pj_fwd
<
has_manipulator
,
Args
>::
type
...
>
tuple_type
;
// applies implicit conversions etc
tuple_type
tup
{
std
::
forward
<
Args
>
(
args
)...};
auto
&
type_token
=
typeid
(
typename
tuple_type
::
types
);
auto
enabled_begin
=
get_cache_entry
(
&
type_token
,
tup
);
typedef
typename
util
::
if_else_c
<
has_manipulator
,
tuple_type
&
,
util
::
wrapped
<
tuple_type
const
&>
>::
type
ref_type
;
typedef
typename
util
::
if_else_c
<
has_manipulator
,
void
*
,
util
::
wrapped
<
void
const
*>
>::
type
ptr_type
;
eval_order
token
;
invoke_helper
<
decltype
(
m_leaves
),
decltype
(
enabled_begin
)
>
fun
{
m_leaves
,
enabled_begin
};
return
util
::
static_foreach
<
0
,
eval_order
::
size
>
::
eval_or
(
token
,
fun
,
type_token
,
detail
::
statically_typed
,
static_cast
<
ptr_type
>
(
nullptr
),
static_cast
<
ref_type
>
(
tup
));
}
template
<
class
...
Rhs
>
projected_fun
<
Leaves
...,
Rhs
...
>
or_else
(
projected_fun
<
Rhs
...
>
const
&
other
)
const
{
detail
::
tdata
<
ge_reference_wrapper
<
Leaves
>
...,
ge_reference_wrapper
<
Rhs
>
...
>
all_leaves
;
collect_tdata
(
all_leaves
,
m_leaves
,
other
.
leaves
());
return
{
all_leaves
};
}
inline
detail
::
tdata
<
Leaves
...
>
const
&
leaves
()
const
{
return
m_leaves
;
}
private:
// structure: tdata< tdata<type_list<...>, ...>,
// tdata<type_list<...>, ...>,
// ...>
detail
::
tdata
<
Leaves
...
>
m_leaves
;
static
constexpr
size_t
cache_size
=
10
;
typedef
std
::
array
<
bool
,
eval_order
::
size
>
cache_entry
;
typedef
typename
cache_entry
::
iterator
cache_entry_iterator
;
typedef
std
::
pair
<
std
::
type_info
const
*
,
cache_entry
>
cache_element
;
util
::
fixed_vector
<
cache_element
,
cache_size
>
m_cache
;
// ring buffer like access to m_cache
size_t
m_cache_begin
;
size_t
m_cache_end
;
cache_element
m_dummy
;
static
inline
void
advance_
(
size_t
&
i
)
{
i
=
(
i
+
1
)
%
cache_size
;
}
inline
size_t
find_token_pos
(
std
::
type_info
const
*
type_token
)
{
for
(
size_t
i
=
m_cache_begin
;
i
!=
m_cache_end
;
advance_
(
i
))
{
if
(
m_cache
[
i
].
first
==
type_token
)
return
i
;
}
return
m_cache_end
;
}
template
<
class
Tuple
>
cache_entry_iterator
get_cache_entry
(
std
::
type_info
const
*
type_token
,
Tuple
const
&
value
)
{
CPPA_REQUIRE
(
type_token
!=
nullptr
);
if
(
value
.
impl_type
()
==
detail
::
dynamically_typed
)
{
return
m_dummy
.
second
.
begin
();
}
size_t
i
=
find_token_pos
(
type_token
);
// if we didn't found a cache entry ...
if
(
i
==
m_cache_end
)
{
// ... 'create' one
advance_
(
m_cache_end
);
if
(
m_cache_end
==
m_cache_begin
)
advance_
(
m_cache_begin
);
m_cache
[
i
].
first
=
type_token
;
eval_order
token
;
can_invoke_helper
<
cache_entry
>
fun
{
m_cache
[
i
].
second
};
util
::
static_foreach
<
0
,
eval_order
::
size
>
::
_
(
token
,
fun
,
*
type_token
,
value
);
}
return
m_cache
[
i
].
second
.
begin
();
}
void
init
()
{
m_dummy
.
second
.
fill
(
true
);
m_cache
.
resize
(
cache_size
);
for
(
size_t
i
=
0
;
i
<
cache_size
;
++
i
)
m_cache
[
i
].
first
=
nullptr
;
m_cache_begin
=
m_cache_end
=
0
;
}
template
<
typename
AbstractTuple
,
typename
NativeDataPtr
>
bool
_do_invoke
(
AbstractTuple
&
vals
,
NativeDataPtr
ndp
)
{
std
::
type_info
const
*
type_token
=
vals
.
type_token
();
auto
enabled_begin
=
get_cache_entry
(
type_token
,
vals
);
eval_order
token
;
invoke_helper
<
decltype
(
m_leaves
),
decltype
(
enabled_begin
)
>
fun
{
m_leaves
,
enabled_begin
};
return
util
::
static_foreach
<
0
,
eval_order
::
size
>
::
eval_or
(
token
,
fun
,
*
type_token
,
vals
.
impl_type
(),
ndp
,
vals
);
}
template
<
typename
AnyTuple
>
bool
_invoke
(
AnyTuple
&
tup
,
typename
util
::
enable_if_c
<
std
::
is_const
<
AnyTuple
>::
value
==
false
&&
has_manipulator
==
true
>::
type
*
=
0
)
{
tup
.
force_detach
();
auto
&
vals
=
*
(
tup
.
vals
());
return
_do_invoke
(
vals
,
vals
.
mutable_native_data
());
}
template
<
typename
AnyTuple
>
bool
_invoke
(
AnyTuple
&
tup
,
typename
util
::
enable_if_c
<
std
::
is_const
<
AnyTuple
>::
value
==
false
&&
has_manipulator
==
false
>::
type
*
=
0
)
{
return
_invoke
(
static_cast
<
AnyTuple
const
&>
(
tup
));
}
template
<
typename
AnyTuple
>
bool
_invoke
(
AnyTuple
&
tup
,
typename
util
::
enable_if_c
<
std
::
is_const
<
AnyTuple
>::
value
==
true
&&
has_manipulator
==
false
>::
type
*
=
0
)
{
auto
const
&
cvals
=
*
(
tup
.
cvals
());
return
_do_invoke
(
cvals
,
cvals
.
native_data
());
}
template
<
typename
AnyTuple
>
bool
_invoke
(
AnyTuple
&
tup
,
typename
util
::
enable_if_c
<
std
::
is_const
<
AnyTuple
>::
value
==
true
&&
has_manipulator
==
true
>::
type
*
=
0
)
{
any_tuple
tup_copy
{
tup
};
return
_invoke
(
tup_copy
);
}
};
template
<
class
List
>
struct
projected_fun_from_type_list
;
template
<
typename
...
Args
>
struct
projected_fun_from_type_list
<
util
::
type_list
<
Args
...
>
>
{
typedef
projected_fun
<
Args
...
>
type
;
};
template
<
typename
...
Lhs
,
typename
...
Rhs
>
projected_fun
<
Lhs
...,
Rhs
...
>
operator
,(
projected_fun
<
Lhs
...
>
const
&
lhs
,
projected_fun
<
Rhs
...
>
const
&
rhs
)
{
return
lhs
.
or_else
(
rhs
);
}
template
<
typename
Arg0
,
typename
...
Args
>
typename
projected_fun_from_type_list
<
typename
util
::
tl_concat
<
typename
Arg0
::
leaves_list
,
typename
Args
::
leaves_list
...
>::
type
>::
type
pj_concat
(
Arg0
const
&
arg0
,
Args
const
&
...
args
)
{
typename
detail
::
tdata_from_type_list
<
typename
util
::
tl_map
<
typename
util
::
tl_concat
<
typename
Arg0
::
leaves_list
,
typename
Args
::
leaves_list
...
>::
type
,
gref_wrapped
>::
type
>::
type
all_leaves
;
collect_tdata
(
all_leaves
,
arg0
.
leaves
(),
args
.
leaves
()...);
return
{
all_leaves
};
}
#define VERBOSE(LineOfCode) cout << #LineOfCode << " = " << (LineOfCode) << endl
struct
cf_builder_from_args
{
};
template
<
class
Guard
,
class
Transformers
,
class
Pattern
>
struct
cf_builder
{
typedef
typename
detail
::
tdata_from_type_list
<
Transformers
>::
type
fun_container
;
Guard
m_guard
;
typename
detail
::
tdata_from_type_list
<
Transformers
>::
type
m_funs
;
public:
cf_builder
()
=
default
;
template
<
typename
...
Args
>
cf_builder
(
cf_builder_from_args
const
&
,
Args
const
&
...
args
)
:
m_guard
(
args
...)
,
m_funs
(
args
...)
{
}
cf_builder
(
Guard
&
mg
,
fun_container
const
&
funs
)
:
m_guard
(
std
::
move
(
mg
)),
m_funs
(
funs
)
{
}
cf_builder
(
Guard
const
&
mg
,
fun_container
const
&
funs
)
:
m_guard
(
mg
),
m_funs
(
funs
)
{
}
template
<
typename
NewGuard
>
cf_builder
<
guard_expr
<
logical_and_op
,
guard_expr
<
exec_xfun_op
,
Guard
,
util
::
void_type
>
,
NewGuard
>
,
Transformers
,
Pattern
>
when
(
NewGuard
ng
,
typename
util
::
disable_if_c
<
std
::
is_same
<
NewGuard
,
NewGuard
>::
value
&&
std
::
is_same
<
Guard
,
value_guard
<
util
::
type_list
<>
>>::
value
>::
type
*
=
0
)
const
{
return
{(
gcall
(
m_guard
)
&&
ng
),
m_funs
};
}
template
<
typename
NewGuard
>
cf_builder
<
NewGuard
,
Transformers
,
Pattern
>
when
(
NewGuard
ng
,
typename
util
::
enable_if_c
<
std
::
is_same
<
NewGuard
,
NewGuard
>::
value
&&
std
::
is_same
<
Guard
,
value_guard
<
util
::
type_list
<>
>>::
value
>::
type
*
=
0
)
const
{
return
{
ng
,
m_funs
};
}
template
<
typename
Expr
>
projected_fun
<
typename
get_cfl
<
Expr
,
Guard
,
Transformers
,
Pattern
>::
type
>
operator
>>
(
Expr
expr
)
const
{
typedef
typename
get_cfl
<
Expr
,
Guard
,
Transformers
,
Pattern
>::
type
tpair
;
return
tpair
{
typename
tpair
::
first_type
{
m_funs
},
typename
tpair
::
second_type
{
std
::
move
(
expr
),
m_guard
}};
}
};
template
<
bool
IsFun
,
typename
T
>
struct
add_ptr_to_fun_
{
typedef
T
*
type
;
};
template
<
typename
T
>
struct
add_ptr_to_fun_
<
false
,
T
>
{
typedef
T
type
;
};
template
<
typename
T
>
struct
add_ptr_to_fun
:
add_ptr_to_fun_
<
std
::
is_function
<
T
>::
value
,
T
>
{
};
template
<
bool
ToVoid
,
typename
T
>
struct
to_void_impl
{
typedef
util
::
void_type
type
;
};
template
<
typename
T
>
struct
to_void_impl
<
false
,
T
>
{
typedef
typename
add_ptr_to_fun
<
T
>::
type
type
;
};
template
<
typename
T
>
struct
not_callable_to_void
:
to_void_impl
<
detail
::
is_boxed
<
T
>::
value
||
!
util
::
is_callable
<
T
>::
value
,
T
>
{
};
template
<
typename
T
>
struct
boxed_and_callable_to_void
:
to_void_impl
<
detail
::
is_boxed
<
T
>::
value
||
util
::
is_callable
<
T
>::
value
,
T
>
{
};
template
<
bool
IsCallable
,
typename
T
>
struct
pattern_type_
{
typedef
util
::
get_callable_trait
<
T
>
ctrait
;
typedef
typename
ctrait
::
arg_types
args
;
static_assert
(
args
::
size
==
1
,
"only unary functions allowed"
);
typedef
typename
util
::
rm_ref
<
typename
args
::
head
>::
type
type
;
};
template
<
typename
T
>
struct
pattern_type_
<
false
,
T
>
{
typedef
typename
util
::
rm_ref
<
typename
detail
::
unboxed
<
T
>::
type
>::
type
type
;
};
template
<
typename
T
>
struct
pattern_type
:
pattern_type_
<
util
::
is_callable
<
T
>::
value
&&
!
detail
::
is_boxed
<
T
>::
value
,
T
>
{
};
template
<
typename
...
T
>
cf_builder
<
value_guard
<
util
::
type_list
<>
>
,
util
::
type_list
<>
,
util
::
type_list
<
T
...
>
>
_on
()
{
return
{};
}
template
<
typename
Arg0
,
typename
...
Args
>
cf_builder
<
value_guard
<
typename
util
::
tl_trim
<
typename
util
::
tl_map
<
util
::
type_list
<
Arg0
,
Args
...
>
,
boxed_and_callable_to_void
>::
type
>::
type
>
,
typename
util
::
tl_map
<
util
::
type_list
<
Arg0
,
Args
...
>
,
not_callable_to_void
>::
type
,
util
::
type_list
<
typename
pattern_type
<
Arg0
>::
type
,
typename
pattern_type
<
Args
>::
type
...
>
>
_on
(
Arg0
const
&
arg0
,
Args
const
&
...
args
)
{
return
{
cf_builder_from_args
{},
arg0
,
args
...};
}
std
::
string
int2str
(
int
i
)
{
return
std
::
to_string
(
i
);
...
...
@@ -1153,14 +124,14 @@ size_t test__tuple()
std
::
string
invoked
;
auto
f00
=
_
on
<
int
,
int
>
()
>>
[
&
]()
{
invoked
=
"f00"
;
};
auto
f00
=
on
<
int
,
int
>
()
>>
[
&
]()
{
invoked
=
"f00"
;
};
CPPA_CHECK_INVOKED
(
f00
,
(
42
,
42
));
auto
f01
=
_
on
<
int
,
int
>
().
when
(
_x1
==
42
)
>>
[
&
]()
{
invoked
=
"f01"
;
};
auto
f01
=
on
<
int
,
int
>
().
when
(
_x1
==
42
)
>>
[
&
]()
{
invoked
=
"f01"
;
};
CPPA_CHECK_INVOKED
(
f01
,
(
42
,
42
));
CPPA_CHECK_NOT_INVOKED
(
f01
,
(
1
,
2
));
auto
f02
=
_
on
<
int
,
int
>
().
when
(
_x1
==
42
&&
_x2
*
2
==
_x1
)
>>
[
&
]()
{
invoked
=
"f02"
;
};
auto
f02
=
on
<
int
,
int
>
().
when
(
_x1
==
42
&&
_x2
*
2
==
_x1
)
>>
[
&
]()
{
invoked
=
"f02"
;
};
CPPA_CHECK_NOT_INVOKED
(
f02
,
(
0
,
0
));
CPPA_CHECK_NOT_INVOKED
(
f02
,
(
42
,
42
));
CPPA_CHECK_NOT_INVOKED
(
f02
,
(
2
,
1
));
...
...
@@ -1170,11 +141,11 @@ size_t test__tuple()
CPPA_CHECK_EQUAL
(
"f02"
,
invoked
);
invoked
=
""
;
auto
f03
=
_
on
(
42
,
val
<
int
>
)
>>
[
&
](
int
const
&
a
,
int
&
)
{
invoked
=
"f03"
;
CPPA_CHECK_EQUAL
(
42
,
a
);
};
auto
f03
=
on
(
42
,
val
<
int
>
)
>>
[
&
](
int
const
&
a
,
int
&
)
{
invoked
=
"f03"
;
CPPA_CHECK_EQUAL
(
42
,
a
);
};
CPPA_CHECK_NOT_INVOKED
(
f03
,
(
0
,
0
));
CPPA_CHECK_INVOKED
(
f03
,
(
42
,
42
));
auto
f04
=
_
on
(
42
,
int2str
).
when
(
_x2
==
"42"
)
>>
[
&
](
std
::
string
&
str
)
auto
f04
=
on
(
42
,
int2str
).
when
(
_x2
==
"42"
)
>>
[
&
](
std
::
string
&
str
)
{
CPPA_CHECK_EQUAL
(
"42"
,
str
);
invoked
=
"f04"
;
...
...
@@ -1185,17 +156,17 @@ size_t test__tuple()
CPPA_CHECK_NOT_INVOKED
(
f04
,
(
42
,
0
));
CPPA_CHECK_INVOKED
(
f04
,
(
42
,
42
));
auto
f05
=
_
on
(
str2int
).
when
(
_x1
%
2
==
0
)
>>
[
&
]()
{
invoked
=
"f05"
;
};
auto
f05
=
on
(
str2int
).
when
(
_x1
%
2
==
0
)
>>
[
&
]()
{
invoked
=
"f05"
;
};
CPPA_CHECK_NOT_INVOKED
(
f05
,
(
"1"
));
CPPA_CHECK_INVOKED
(
f05
,
(
"2"
));
auto
f06
=
_
on
(
42
,
str2int
).
when
(
_x2
%
2
==
0
)
>>
[
&
]()
{
invoked
=
"f06"
;
};
auto
f06
=
on
(
42
,
str2int
).
when
(
_x2
%
2
==
0
)
>>
[
&
]()
{
invoked
=
"f06"
;
};
CPPA_CHECK_NOT_INVOKED
(
f06
,
(
0
,
"0"
));
CPPA_CHECK_NOT_INVOKED
(
f06
,
(
42
,
"1"
));
CPPA_CHECK_INVOKED
(
f06
,
(
42
,
"2"
));
int
f07_val
=
1
;
auto
f07
=
_
on
<
int
>
().
when
(
_x1
==
gref
(
f07_val
))
>>
[
&
]()
{
invoked
=
"f07"
;
};
auto
f07
=
on
<
int
>
().
when
(
_x1
==
gref
(
f07_val
))
>>
[
&
]()
{
invoked
=
"f07"
;
};
CPPA_CHECK_NOT_INVOKED
(
f07
,
(
0
));
CPPA_CHECK_INVOKED
(
f07
,
(
1
));
CPPA_CHECK_NOT_INVOKED
(
f07
,
(
2
));
...
...
@@ -1206,7 +177,7 @@ size_t test__tuple()
CPPA_CHECK
(
f07
.
invoke
(
make_cow_tuple
(
2
)));
int
f08_val
=
666
;
auto
f08
=
_
on
<
int
>
()
>>
[
&
](
int
&
mref
)
{
mref
=
8
;
invoked
=
"f08"
;
};
auto
f08
=
on
<
int
>
()
>>
[
&
](
int
&
mref
)
{
mref
=
8
;
invoked
=
"f08"
;
};
CPPA_CHECK_INVOKED
(
f08
,
(
f08_val
));
CPPA_CHECK_EQUAL
(
8
,
f08_val
);
any_tuple
f08_any_val
=
make_cow_tuple
(
666
);
...
...
@@ -1214,7 +185,7 @@ size_t test__tuple()
CPPA_CHECK_EQUAL
(
8
,
f08_any_val
.
get_as
<
int
>
(
0
));
int
f09_val
=
666
;
auto
f09
=
_
on
(
str2int
,
val
<
int
>
)
>>
[
&
](
int
&
mref
)
{
mref
=
9
;
invoked
=
"f09"
;
};
auto
f09
=
on
(
str2int
,
val
<
int
>
)
>>
[
&
](
int
&
mref
)
{
mref
=
9
;
invoked
=
"f09"
;
};
CPPA_CHECK_NOT_INVOKED
(
f09
,
(
"hello lambda"
,
f09_val
));
CPPA_CHECK_INVOKED
(
f09
,
(
"0"
,
f09_val
));
CPPA_CHECK_EQUAL
(
9
,
f09_val
);
...
...
@@ -1233,9 +204,9 @@ size_t test__tuple()
auto
f10
=
(
_
on
<
int
>
().
when
(
_x1
<
10
)
>>
[
&
]()
{
invoked
=
"f10.0"
;
},
_
on
<
int
>
()
>>
[
&
]()
{
invoked
=
"f10.1"
;
},
_
on
<
std
::
string
,
anything
>
()
>>
[
&
](
std
::
string
&
)
{
invoked
=
"f10.2"
;
}
on
<
int
>
().
when
(
_x1
<
10
)
>>
[
&
]()
{
invoked
=
"f10.0"
;
},
on
<
int
>
()
>>
[
&
]()
{
invoked
=
"f10.1"
;
},
on
<
std
::
string
,
anything
>
()
>>
[
&
](
std
::
string
&
)
{
invoked
=
"f10.2"
;
}
);
CPPA_CHECK
(
f10
(
9
));
...
...
@@ -1252,19 +223,19 @@ size_t test__tuple()
//CPPA_CHECK(f10(static_cast<std::string const&>(foobar), "b", "c"));
int
f11_fun
=
0
;
auto
f11
=
pj_concat
auto
f11
=
(
_
on
<
int
>
().
when
(
_x1
==
1
)
>>
[
&
]()
{
f11_fun
=
1
;
},
_
on
<
int
>
().
when
(
_x1
==
2
)
>>
[
&
]()
{
f11_fun
=
2
;
},
_
on
<
int
>
().
when
(
_x1
==
3
)
>>
[
&
]()
{
f11_fun
=
3
;
},
_
on
<
int
>
().
when
(
_x1
==
4
)
>>
[
&
]()
{
f11_fun
=
4
;
},
_
on
<
int
>
().
when
(
_x1
==
5
)
>>
[
&
]()
{
f11_fun
=
5
;
},
_
on
<
int
>
().
when
(
_x1
==
6
)
>>
[
&
]()
{
f11_fun
=
6
;
},
_
on
<
int
>
().
when
(
_x1
==
7
)
>>
[
&
]()
{
f11_fun
=
7
;
},
_
on
<
int
>
().
when
(
_x1
==
8
)
>>
[
&
]()
{
f11_fun
=
8
;
},
_
on
<
int
>
().
when
(
_x1
>=
9
)
>>
[
&
]()
{
f11_fun
=
9
;
},
_
on
(
str2int
)
>>
[
&
]()
{
f11_fun
=
10
;
},
_
on
<
std
::
string
>
()
>>
[
&
]()
{
f11_fun
=
11
;
}
on
<
int
>
().
when
(
_x1
==
1
)
>>
[
&
]()
{
f11_fun
=
1
;
},
on
<
int
>
().
when
(
_x1
==
2
)
>>
[
&
]()
{
f11_fun
=
2
;
},
on
<
int
>
().
when
(
_x1
==
3
)
>>
[
&
]()
{
f11_fun
=
3
;
},
on
<
int
>
().
when
(
_x1
==
4
)
>>
[
&
]()
{
f11_fun
=
4
;
},
on
<
int
>
().
when
(
_x1
==
5
)
>>
[
&
]()
{
f11_fun
=
5
;
},
on
<
int
>
().
when
(
_x1
==
6
)
>>
[
&
]()
{
f11_fun
=
6
;
},
on
<
int
>
().
when
(
_x1
==
7
)
>>
[
&
]()
{
f11_fun
=
7
;
},
on
<
int
>
().
when
(
_x1
==
8
)
>>
[
&
]()
{
f11_fun
=
8
;
},
on
<
int
>
().
when
(
_x1
>=
9
)
>>
[
&
]()
{
f11_fun
=
9
;
},
on
(
str2int
)
>>
[
&
]()
{
f11_fun
=
10
;
},
on
<
std
::
string
>
()
>>
[
&
]()
{
f11_fun
=
11
;
}
);
CPPA_CHECK
(
f11
(
1
));
...
...
@@ -1280,9 +251,9 @@ size_t test__tuple()
CPPA_CHECK
(
f11
(
"10"
));
CPPA_CHECK_EQUAL
(
10
,
f11_fun
);
auto
f12
=
pj_concat
auto
f12
=
(
_
on
<
int
,
anything
,
int
>
().
when
(
_x1
<
_x2
)
>>
[
&
](
int
a
,
int
b
)
on
<
int
,
anything
,
int
>
().
when
(
_x1
<
_x2
)
>>
[
&
](
int
a
,
int
b
)
{
CPPA_CHECK_EQUAL
(
1
,
a
);
CPPA_CHECK_EQUAL
(
5
,
b
);
...
...
@@ -1292,9 +263,9 @@ size_t test__tuple()
CPPA_CHECK_INVOKED
(
f12
,
(
1
,
2
,
3
,
4
,
5
));
int
f13_fun
=
0
;
auto
f13
=
pj_concat
auto
f13
=
(
_
on
<
int
,
anything
,
std
::
string
,
anything
,
int
>
().
when
(
_x1
<
_x3
&&
_x2
.
starts_with
(
"-"
))
>>
[
&
](
int
a
,
std
::
string
const
&
str
,
int
b
)
on
<
int
,
anything
,
std
::
string
,
anything
,
int
>
().
when
(
_x1
<
_x3
&&
_x2
.
starts_with
(
"-"
))
>>
[
&
](
int
a
,
std
::
string
const
&
str
,
int
b
)
{
CPPA_CHECK_EQUAL
(
"-h"
,
str
);
CPPA_CHECK_EQUAL
(
1
,
a
);
...
...
@@ -1302,7 +273,7 @@ size_t test__tuple()
f13_fun
=
1
;
invoked
=
"f13"
;
},
_
on
<
anything
,
std
::
string
,
anything
,
int
,
anything
,
float
,
anything
>
()
>>
[
&
](
std
::
string
const
&
str
,
int
a
,
float
b
)
on
<
anything
,
std
::
string
,
anything
,
int
,
anything
,
float
,
anything
>
()
>>
[
&
](
std
::
string
const
&
str
,
int
a
,
float
b
)
{
CPPA_CHECK_EQUAL
(
"h"
,
str
);
CPPA_CHECK_EQUAL
(
12
,
a
);
...
...
@@ -1310,7 +281,7 @@ size_t test__tuple()
f13_fun
=
2
;
invoked
=
"f13"
;
},
_
on
<
float
,
anything
,
float
>
().
when
(
_x1
*
2
==
_x2
)
>>
[
&
](
float
a
,
float
b
)
on
<
float
,
anything
,
float
>
().
when
(
_x1
*
2
==
_x2
)
>>
[
&
](
float
a
,
float
b
)
{
CPPA_CHECK_EQUAL
(
1.
f
,
a
);
CPPA_CHECK_EQUAL
(
2.
f
,
b
);
...
...
@@ -1339,10 +310,10 @@ size_t test__tuple()
auto
new_pf
=
(
_
on
(
42
)
>>
[]()
{
},
_
on
(
std
::
string
(
"abc"
))
>>
[]()
{
},
_
on
<
int
,
int
>
()
>>
[]()
{
},
_
on
<
anything
>
()
>>
[]()
{
}
on
(
42
)
>>
[]()
{
},
on
(
std
::
string
(
"abc"
))
>>
[]()
{
},
on
<
int
,
int
>
()
>>
[]()
{
},
on
<
anything
>
()
>>
[]()
{
}
);
any_tuple
testee
[]
=
{
...
...
@@ -1462,10 +433,10 @@ size_t test__tuple()
{
auto
tmp
=
(
_
on
(
42
)
>>
[]()
{
},
_
on
(
std
::
string
(
"abc"
))
>>
[]()
{
},
_
on
<
int
,
int
>
()
>>
[]()
{
},
_
on
<
anything
>
()
>>
[]()
{
}
on
(
42
)
>>
[]()
{
},
on
(
std
::
string
(
"abc"
))
>>
[]()
{
},
on
<
int
,
int
>
()
>>
[]()
{
},
on
<
anything
>
()
>>
[]()
{
}
);
for
(
auto
&
x
:
testee
)
{
tmp
(
x
);
}
}
...
...
@@ -1490,13 +461,13 @@ size_t test__tuple()
VERBOSE(f05(42, std::string("42")));
VERBOSE(f05(42, std::string("hello world!")));
auto f06 = f04.or_else(
_
on<int, int>().when(_x2 > _x1) >> []() { });
auto f06 = f04.or_else(on<int, int>().when(_x2 > _x1) >> []() { });
VERBOSE(f06(42, 42));
VERBOSE(f06(1, 2));
*/
/*
auto f06 =
_
on<anything, int>() >> []() { };
auto f06 = on<anything, int>() >> []() { };
VERBOSE(f06(1));
VERBOSE(f06(1.f, 2));
...
...
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