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
00f15911
Commit
00f15911
authored
Apr 06, 2012
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
guard expressions
parent
3652f62e
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
827 additions
and
389 deletions
+827
-389
Makefile.am
Makefile.am
+1
-1
cppa.files
cppa.files
+1
-1
cppa/detail/invokable.hpp
cppa/detail/invokable.hpp
+1
-1
cppa/detail/tdata.hpp
cppa/detail/tdata.hpp
+2
-2
cppa/guard_expr.hpp
cppa/guard_expr.hpp
+656
-0
cppa/on.hpp
cppa/on.hpp
+28
-1
cppa/util/apply_tuple.hpp
cppa/util/apply_tuple.hpp
+16
-10
cppa/util/type_list.hpp
cppa/util/type_list.hpp
+14
-0
unit_testing/test__match.cpp
unit_testing/test__match.cpp
+107
-372
unit_testing/test__spawn.cpp
unit_testing/test__spawn.cpp
+1
-1
No files found.
Makefile.am
View file @
00f15911
...
@@ -151,6 +151,7 @@ nobase_library_include_HEADERS = \
...
@@ -151,6 +151,7 @@ nobase_library_include_HEADERS = \
cppa/fsm_actor.hpp
\
cppa/fsm_actor.hpp
\
cppa/get.hpp
\
cppa/get.hpp
\
cppa/group.hpp
\
cppa/group.hpp
\
cppa/guard_expr.hpp
\
cppa/intrusive/forward_iterator.hpp
\
cppa/intrusive/forward_iterator.hpp
\
cppa/intrusive/single_reader_queue.hpp
\
cppa/intrusive/single_reader_queue.hpp
\
cppa/intrusive/singly_linked_list.hpp
\
cppa/intrusive/singly_linked_list.hpp
\
...
@@ -192,7 +193,6 @@ nobase_library_include_HEADERS = \
...
@@ -192,7 +193,6 @@ nobase_library_include_HEADERS = \
cppa/util/enable_if.hpp
\
cppa/util/enable_if.hpp
\
cppa/util/fiber.hpp
\
cppa/util/fiber.hpp
\
cppa/util/fixed_vector.hpp
\
cppa/util/fixed_vector.hpp
\
cppa/util/guard.hpp
\
cppa/util/if_else.hpp
\
cppa/util/if_else.hpp
\
cppa/util/is_array_of.hpp
\
cppa/util/is_array_of.hpp
\
cppa/util/is_builtin.hpp
\
cppa/util/is_builtin.hpp
\
...
...
cppa.files
View file @
00f15911
...
@@ -258,5 +258,5 @@ cppa/detail/tuple_view.hpp
...
@@ -258,5 +258,5 @@ cppa/detail/tuple_view.hpp
cppa/detail/container_tuple_view.hpp
cppa/detail/container_tuple_view.hpp
cppa/detail/matches.hpp
cppa/detail/matches.hpp
unit_testing/test__match.cpp
unit_testing/test__match.cpp
cppa/guard_expr.hpp
src/pattern.cpp
src/pattern.cpp
cppa/util/guard.hpp
cppa/detail/invokable.hpp
View file @
00f15911
...
@@ -163,7 +163,7 @@ enum mapping_policy
...
@@ -163,7 +163,7 @@ enum mapping_policy
map_to_option
map_to_option
};
};
template
<
mapping_policy
,
class
Pattern
>
template
<
mapping_policy
,
class
Pattern
>
// do_not_map
struct
pattern_policy
struct
pattern_policy
{
{
Pattern
m_pattern
;
Pattern
m_pattern
;
...
...
cppa/detail/tdata.hpp
View file @
00f15911
...
@@ -267,9 +267,9 @@ template<typename T>
...
@@ -267,9 +267,9 @@ template<typename T>
struct
tdata_from_type_list
;
struct
tdata_from_type_list
;
template
<
typename
...
T
>
template
<
typename
...
T
>
struct
tdata_from_type_list
<
cppa
::
util
::
type_list
<
T
...
>>
struct
tdata_from_type_list
<
util
::
type_list
<
T
...
>>
{
{
typedef
cppa
::
detail
::
tdata
<
T
...
>
type
;
typedef
tdata
<
T
...
>
type
;
};
};
}
}
// namespace cppa::detail
}
}
// namespace cppa::detail
...
...
cppa/guard_expr.hpp
0 → 100644
View file @
00f15911
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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 GUARD_EXPR_HPP
#define GUARD_EXPR_HPP
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <type_traits>
#include "cppa/util/at.hpp"
#include "cppa/detail/tdata.hpp"
namespace
cppa
{
enum
operator_id
{
// arithmetic operators
addition_op
,
subtraction_op
,
multiplication_op
,
division_op
,
modulo_op
,
// comparison operators
less_op
,
less_eq_op
,
greater_op
,
greater_eq_op
,
equal_op
,
not_equal_op
,
// logical operators
logical_and_op
,
logical_or_op
,
// pseudo operators for function invocation
exec_fun1_op
,
exec_fun2_op
,
exec_fun3_op
,
// pseudo operator to store function parameters
dummy_op
};
// {operator, lhs, rhs} expression
template
<
operator_id
OP
,
typename
First
,
typename
Second
>
struct
guard_expr
{
typedef
First
first_type
;
typedef
Second
second_type
;
std
::
pair
<
First
,
Second
>
m_args
;
//guard_expr() = default;
template
<
typename
T0
,
typename
T1
>
guard_expr
(
T0
&&
a0
,
T1
&&
a1
)
:
m_args
(
std
::
forward
<
T0
>
(
a0
),
std
::
forward
<
T1
>
(
a1
))
{
}
// {operator, {operator, a0, a1}, a2}
template
<
typename
T0
,
typename
T1
,
typename
T2
>
guard_expr
(
T0
&&
a0
,
T1
&&
a1
,
T2
&&
a2
)
:
m_args
(
First
{
std
::
forward
<
T0
>
(
a0
),
std
::
forward
<
T1
>
(
a1
)},
std
::
forward
<
T2
>
(
a2
))
{
}
// {operator, {operator, a0, a1}, {operator, a2, a3}}
template
<
typename
T0
,
typename
T1
,
typename
T2
,
typename
T3
>
guard_expr
(
T0
&&
a0
,
T1
&&
a1
,
T2
&&
a2
,
T3
&&
a3
)
:
m_args
(
First
{
std
::
forward
<
T0
>
(
a0
),
std
::
forward
<
T1
>
(
a1
)},
Second
{
std
::
forward
<
T2
>
(
a2
),
std
::
forward
<
T3
>
(
a3
)})
{
}
guard_expr
(
guard_expr
const
&
)
=
default
;
guard_expr
(
guard_expr
&&
other
)
:
m_args
(
std
::
move
(
other
.
m_args
))
{
}
};
#define CPPA_FORALL_OPS(SubMacro) \
SubMacro (addition_op, +) SubMacro (subtraction_op, -) \
SubMacro (multiplication_op, *) SubMacro (division_op, /) \
SubMacro (modulo_op, %) SubMacro (less_op, <) \
SubMacro (less_eq_op, <=) SubMacro (greater_op, >) \
SubMacro (greater_eq_op, >=) SubMacro (equal_op, ==) \
SubMacro (not_equal_op, !=)
// bind utility for placeholders
template
<
typename
Fun
,
typename
T1
>
struct
gbind1
{
typedef
guard_expr
<
exec_fun1_op
,
Fun
,
T1
>
result
;
};
template
<
typename
Fun
,
typename
T1
,
typename
T2
>
struct
gbind2
{
typedef
guard_expr
<
exec_fun2_op
,
guard_expr
<
dummy_op
,
Fun
,
T1
>
,
T2
>
result
;
};
template
<
typename
Fun
,
typename
T1
,
typename
T2
,
typename
T3
>
struct
gbind3
{
typedef
guard_expr
<
exec_fun3_op
,
guard_expr
<
dummy_op
,
Fun
,
T1
>
,
guard_expr
<
dummy_op
,
T2
,
T3
>
>
result
;
};
/**
* @brief Call wrapper for guard placeholders and lazy evaluation.
*/
template
<
typename
Fun
,
typename
T1
>
typename
gbind1
<
Fun
,
T1
>::
result
gbind
(
Fun
fun
,
T1
t1
)
{
return
{
fun
,
t1
};
}
/**
* @brief Call wrapper for guard placeholders and lazy evaluation.
*/
template
<
typename
Fun
,
typename
T1
,
typename
T2
>
typename
gbind2
<
Fun
,
T1
,
T2
>::
result
gbind
(
Fun
fun
,
T1
t1
,
T2
t2
)
{
return
{
fun
,
t1
,
t2
};
}
/**
* @brief Call wrapper for guard placeholders and lazy evaluation.
*/
template
<
typename
Fun
,
typename
T1
,
typename
T2
,
typename
T3
>
typename
gbind3
<
Fun
,
T1
,
T2
,
T3
>::
result
gbind
(
Fun
fun
,
T1
t1
,
T2
t2
,
T3
t3
)
{
return
{
fun
,
t1
,
t2
,
t3
};
}
struct
ge_search_container
{
bool
sc
;
ge_search_container
(
bool
should_contain
)
:
sc
(
should_contain
)
{
}
template
<
class
C
>
bool
operator
()(
C
const
&
haystack
,
typename
C
::
value_type
const
&
needle
)
const
{
typedef
typename
C
::
value_type
vtype
;
if
(
sc
)
return
std
::
any_of
(
haystack
.
begin
(),
haystack
.
end
(),
[
&
](
vtype
const
&
val
)
{
return
needle
==
val
;
});
return
std
::
none_of
(
haystack
.
begin
(),
haystack
.
end
(),
[
&
](
vtype
const
&
val
)
{
return
needle
==
val
;
});
}
template
<
class
C
>
bool
operator
()(
std
::
reference_wrapper
<
C
>
const
&
haystack_ref
,
typename
C
::
value_type
const
&
needle
)
const
{
return
(
*
this
)(
haystack_ref
.
get
(),
needle
);
}
};
/**
* @brief A placeholder for guard expression.
*/
template
<
int
X
>
struct
guard_placeholder
{
constexpr
guard_placeholder
()
{
}
/**
* @brief Convenient way to call <tt>gbind(fun, guard_placeholder)</tt>.
*/
template
<
typename
Fun
>
typename
gbind1
<
Fun
,
guard_placeholder
>::
result
operator
()(
Fun
fun
)
const
{
return
gbind
(
fun
,
*
this
);
}
// utility function for starts_with()
static
bool
u8_starts_with
(
std
::
string
const
&
lhs
,
std
::
string
const
&
rhs
)
{
return
std
::
equal
(
rhs
.
begin
(),
rhs
.
end
(),
lhs
.
begin
());
}
/**
* @brief Evaluates to true if unbound argument starts with @p str.
*/
typename
gbind2
<
decltype
(
&
guard_placeholder
::
u8_starts_with
),
guard_placeholder
,
std
::
string
>::
result
starts_with
(
std
::
string
str
)
const
{
return
gbind
(
&
guard_placeholder
::
u8_starts_with
,
*
this
,
str
);
}
/**
* @brief Evaluates to true if unbound argument
* is contained in @p container.
*/
template
<
class
C
>
typename
gbind2
<
ge_search_container
,
C
,
guard_placeholder
>::
result
in
(
C
container
)
const
{
return
gbind
(
ge_search_container
{
true
},
container
,
*
this
);
}
/**
* @brief Evaluates to true if unbound argument
* is contained in @p container.
*/
template
<
class
C
>
typename
gbind2
<
ge_search_container
,
std
::
reference_wrapper
<
C
>
,
guard_placeholder
>::
result
in
(
std
::
reference_wrapper
<
C
>
container
)
const
{
return
gbind
(
ge_search_container
{
true
},
container
,
*
this
);
}
/**
* @brief Evaluates to true if unbound argument
* is contained in @p list.
*/
template
<
typename
T
>
typename
gbind2
<
ge_search_container
,
std
::
vector
<
typename
detail
::
strip_and_convert
<
T
>::
type
>
,
guard_placeholder
>::
result
in
(
std
::
initializer_list
<
T
>
list
)
const
{
std
::
vector
<
typename
detail
::
strip_and_convert
<
T
>::
type
>
vec
;
for
(
auto
&
i
:
list
)
vec
.
emplace_back
(
i
);
return
in
(
vec
);
}
/**
* @brief Evaluates to true if unbound argument
* is not contained in @p container.
*/
template
<
class
C
>
typename
gbind2
<
ge_search_container
,
C
,
guard_placeholder
>::
result
not_in
(
C
container
)
const
{
return
gbind
(
ge_search_container
{
false
},
container
,
*
this
);
}
/**
* @brief Evaluates to true if unbound argument
* is not contained in @p container.
*/
template
<
class
C
>
typename
gbind2
<
ge_search_container
,
std
::
reference_wrapper
<
C
>
,
guard_placeholder
>::
result
not_in
(
std
::
reference_wrapper
<
C
>
container
)
const
{
return
gbind
(
ge_search_container
{
false
},
container
,
*
this
);
}
/**
* @brief Evaluates to true if unbound argument
* is not contained in @p list.
*/
template
<
typename
T
>
typename
gbind2
<
ge_search_container
,
std
::
vector
<
typename
detail
::
strip_and_convert
<
T
>::
type
>
,
guard_placeholder
>::
result
not_in
(
std
::
initializer_list
<
T
>
list
)
const
{
std
::
vector
<
typename
detail
::
strip_and_convert
<
T
>::
type
>
vec
;
for
(
auto
&
i
:
list
)
vec
.
emplace_back
(
i
);
return
not_in
(
vec
);
}
};
// result type computation
template
<
typename
T
,
class
Tuple
>
struct
ge_unbound
{
typedef
T
type
;
};
// unbound type of placeholder
template
<
int
X
,
typename
...
Ts
>
struct
ge_unbound
<
guard_placeholder
<
X
>
,
detail
::
tdata
<
Ts
...
>
>
{
static_assert
(
X
<
sizeof
...(
Ts
),
"Cannot unbind placeholder (too few arguments)"
);
typedef
typename
std
::
remove_pointer
<
typename
util
::
at
<
X
,
Ts
...
>::
type
>::
type
type
;
};
// operators, operators, operators
#define CPPA_GUARD_PLACEHOLDER_OPERATOR(EnumValue, Operator) \
template<int Pos1, int Pos2> \
guard_expr< EnumValue , guard_placeholder<Pos1>, guard_placeholder<Pos2>> \
operator Operator (guard_placeholder<Pos1> p1, guard_placeholder<Pos2> p2) \
{ return {p1, p2}; } \
template<int Pos, typename T> \
guard_expr< EnumValue , guard_placeholder<Pos>, \
typename detail::strip_and_convert<T>::type > \
operator Operator (guard_placeholder<Pos> gp, T value) \
{ return {std::move(gp), std::move(value)}; } \
template<typename T, int Pos> \
guard_expr< EnumValue , \
typename detail::strip_and_convert<T>::type, \
guard_placeholder<Pos> > \
operator Operator (T value, guard_placeholder<Pos> gp) \
{ return {std::move(value), std::move(gp)}; }
CPPA_FORALL_OPS
(
CPPA_GUARD_PLACEHOLDER_OPERATOR
)
#define CPPA_GUARD_EXPR_OPERATOR(EnumValue, Operator) \
template<operator_id OP, typename F, typename S, typename T> \
guard_expr< EnumValue , guard_expr<OP, F, S>, \
typename detail::strip_and_convert<T>::type> \
operator Operator (guard_expr<OP, F, S> lhs, T rhs) \
{ return {lhs, rhs}; } \
template<typename T, operator_id OP, typename F, typename S> \
guard_expr< EnumValue , typename detail::strip_and_convert<T>::type, \
guard_expr<OP, F, S>> \
operator Operator (T lhs, guard_expr<OP, F, S> rhs) \
{ return {lhs, rhs}; } \
template<operator_id OP, typename F, typename S, int X> \
guard_expr< EnumValue , guard_expr<OP, F, S>, guard_placeholder<X> > \
operator Operator (guard_expr<OP, F, S> lhs, guard_placeholder<X> rhs) \
{ return {lhs, rhs}; } \
template<int X, operator_id OP, typename F, typename S> \
guard_expr< EnumValue , guard_placeholder<X>, guard_expr<OP, F, S>> \
operator Operator (guard_placeholder<X> lhs, guard_expr<OP, F, S> rhs) \
{ return {lhs, rhs}; } \
template<operator_id OP1, typename F1, typename S1, \
operator_id OP2, typename F2, typename S2> \
guard_expr< EnumValue , guard_expr<OP1, F1, S1>, guard_expr<OP2, F2, S2>> \
operator Operator (guard_expr<OP1,F1,S1> lhs, guard_expr<OP2,F2,S2> rhs) \
{ return {lhs, rhs}; }
CPPA_FORALL_OPS
(
CPPA_GUARD_EXPR_OPERATOR
)
template
<
operator_id
OP
>
struct
ge_eval_op
;
#define CPPA_EVAL_OP_IMPL(EnumValue, Operator) \
template<> struct ge_eval_op< EnumValue > { \
template<typename T1, typename T2> \
static inline auto _(T1 const& lhs, T2 const& rhs) \
-> decltype(lhs Operator rhs) { return lhs Operator rhs; } \
};
CPPA_FORALL_OPS
(
CPPA_EVAL_OP_IMPL
)
CPPA_EVAL_OP_IMPL
(
logical_and_op
,
&&
)
CPPA_EVAL_OP_IMPL
(
logical_or_op
,
||
)
template
<
typename
T
,
class
Tuple
>
struct
ge_result_
{
typedef
typename
ge_unbound
<
T
,
Tuple
>::
type
type
;
};
template
<
operator_id
OP
,
typename
First
,
typename
Second
,
class
Tuple
>
struct
ge_result_
<
guard_expr
<
OP
,
First
,
Second
>
,
Tuple
>
{
typedef
typename
ge_result_
<
First
,
Tuple
>::
type
lhs_type
;
typedef
typename
ge_result_
<
Second
,
Tuple
>::
type
rhs_type
;
typedef
decltype
(
ge_eval_op
<
OP
>::
_
(
*
static_cast
<
lhs_type
const
*>
(
nullptr
),
*
static_cast
<
rhs_type
const
*>
(
nullptr
)))
type
;
};
template
<
typename
First
,
typename
Second
,
class
Tuple
>
struct
ge_result_
<
guard_expr
<
exec_fun1_op
,
First
,
Second
>
,
Tuple
>
{
typedef
First
type0
;
typedef
typename
ge_unbound
<
Second
,
Tuple
>::
type
type1
;
typedef
decltype
(
(
*
static_cast
<
type0
const
*>
(
nullptr
))(
*
static_cast
<
type1
const
*>
(
nullptr
)
))
type
;
};
template
<
typename
First
,
typename
Second
,
class
Tuple
>
struct
ge_result_
<
guard_expr
<
exec_fun2_op
,
First
,
Second
>
,
Tuple
>
{
typedef
typename
First
::
first_type
type0
;
typedef
typename
ge_unbound
<
typename
First
::
second_type
,
Tuple
>::
type
type1
;
typedef
typename
ge_unbound
<
Second
,
Tuple
>::
type
type2
;
typedef
decltype
(
(
*
static_cast
<
type0
const
*>
(
nullptr
))(
*
static_cast
<
type1
const
*>
(
nullptr
),
*
static_cast
<
type2
const
*>
(
nullptr
)
))
type
;
};
template
<
typename
First
,
typename
Second
,
class
Tuple
>
struct
ge_result_
<
guard_expr
<
exec_fun3_op
,
First
,
Second
>
,
Tuple
>
{
typedef
typename
First
::
first_type
type0
;
typedef
typename
ge_unbound
<
typename
First
::
second_type
,
Tuple
>::
type
type1
;
typedef
typename
ge_unbound
<
typename
Second
::
first_type
,
Tuple
>::
type
type2
;
typedef
typename
ge_unbound
<
typename
Second
::
second_type
,
Tuple
>::
type
type3
;
typedef
decltype
(
(
*
static_cast
<
type0
const
*>
(
nullptr
))(
*
static_cast
<
type1
const
*>
(
nullptr
),
*
static_cast
<
type2
const
*>
(
nullptr
),
*
static_cast
<
type3
const
*>
(
nullptr
)
))
type
;
};
/*
#define CPPA_G_RESULT_TYPE_SPECIALIZATION(EnumValue, Operator) \
template<typename First, typename Second, class Tuple> \
struct ge_result_< guard_expr< EnumValue , First, Second>, Tuple> \
{ \
typedef typename ge_result_<First, Tuple>::type lhs_type; \
typedef typename ge_result_<Second, Tuple>::type rhs_type; \
typedef decltype(*static_cast<lhs_type const*>(nullptr) \
Operator \
*static_cast<rhs_type const*>(nullptr)) type; \
};
CPPA_G_RESULT_TYPE_SPECIALIZATION(addition_op, +)
CPPA_G_RESULT_TYPE_SPECIALIZATION(subtraction_op, -)
CPPA_G_RESULT_TYPE_SPECIALIZATION(multiplication_op, *)
CPPA_G_RESULT_TYPE_SPECIALIZATION(division_op, /)
CPPA_G_RESULT_TYPE_SPECIALIZATION(modulo_op, %)
*/
template
<
operator_id
OP
,
typename
First
,
typename
Second
,
class
Tuple
>
struct
ge_result
{
typedef
typename
ge_result_
<
guard_expr
<
OP
,
First
,
Second
>
,
Tuple
>::
type
type
;
};
template
<
operator_id
OP1
,
typename
F1
,
typename
S1
,
operator_id
OP2
,
typename
F2
,
typename
S2
>
guard_expr
<
logical_and_op
,
guard_expr
<
OP1
,
F1
,
S1
>
,
guard_expr
<
OP2
,
F2
,
S2
>>
operator
&&
(
guard_expr
<
OP1
,
F1
,
S1
>
lhs
,
guard_expr
<
OP2
,
F2
,
S2
>
rhs
)
{
return
{
lhs
,
rhs
};
}
template
<
operator_id
OP1
,
typename
F1
,
typename
S1
,
operator_id
OP2
,
typename
F2
,
typename
S2
>
guard_expr
<
logical_or_op
,
guard_expr
<
OP1
,
F1
,
S1
>
,
guard_expr
<
OP2
,
F2
,
S2
>>
operator
||
(
guard_expr
<
OP1
,
F1
,
S1
>
lhs
,
guard_expr
<
OP2
,
F2
,
S2
>
rhs
)
{
return
{
lhs
,
rhs
};
}
// evaluation of guard_expr
template
<
class
Tuple
,
typename
T
>
inline
T
const
&
ge_resolve
(
Tuple
const
&
,
T
const
&
value
)
{
return
value
;
}
template
<
class
Tuple
,
int
X
>
inline
auto
ge_resolve
(
Tuple
const
&
tup
,
guard_placeholder
<
X
>
)
->
decltype
(
*
get
<
X
>
(
tup
))
{
return
*
get
<
X
>
(
tup
);
}
template
<
class
Tuple
,
operator_id
OP
,
typename
First
,
typename
Second
>
auto
ge_resolve
(
Tuple
const
&
tup
,
guard_expr
<
OP
,
First
,
Second
>
const
&
ge
)
->
typename
ge_result
<
OP
,
First
,
Second
,
Tuple
>::
type
;
template
<
operator_id
OP
,
class
Tuple
,
typename
First
,
typename
Second
>
struct
ge_eval_
{
static
inline
typename
ge_result
<
OP
,
First
,
Second
,
Tuple
>::
type
_
(
Tuple
const
&
tup
,
First
const
&
lhs
,
Second
const
&
rhs
)
{
return
ge_eval_op
<
OP
>::
_
(
ge_resolve
(
tup
,
lhs
),
ge_resolve
(
tup
,
rhs
));
}
};
template
<
class
Tuple
,
typename
First
,
typename
Second
>
struct
ge_eval_
<
logical_and_op
,
Tuple
,
First
,
Second
>
{
static
inline
bool
_
(
Tuple
const
&
tup
,
First
const
&
lhs
,
Second
const
&
rhs
)
{
// emulate short-circuit evaluation
if
(
ge_resolve
(
tup
,
lhs
))
return
ge_resolve
(
tup
,
rhs
);
return
false
;
}
};
template
<
class
Tuple
,
typename
First
,
typename
Second
>
struct
ge_eval_
<
logical_or_op
,
Tuple
,
First
,
Second
>
{
static
inline
bool
_
(
Tuple
const
&
tup
,
First
const
&
lhs
,
Second
const
&
rhs
)
{
// emulate short-circuit evaluation
if
(
ge_resolve
(
tup
,
lhs
))
return
true
;
return
ge_resolve
(
tup
,
rhs
);
}
};
template
<
class
Tuple
,
typename
First
,
typename
Second
>
struct
ge_eval_
<
exec_fun1_op
,
Tuple
,
First
,
Second
>
{
static
inline
auto
_
(
Tuple
const
&
tup
,
First
const
&
fun
,
Second
const
&
arg0
)
->
decltype
(
fun
(
ge_resolve
(
tup
,
arg0
)))
{
return
fun
(
ge_resolve
(
tup
,
arg0
));
}
};
template
<
class
Tuple
,
typename
First
,
typename
Second
>
struct
ge_eval_
<
exec_fun2_op
,
Tuple
,
First
,
Second
>
{
static
inline
auto
_
(
Tuple
const
&
tup
,
First
const
&
lhs
,
Second
const
&
rhs
)
->
decltype
(
lhs
.
m_args
.
first
(
ge_resolve
(
tup
,
lhs
.
m_args
.
second
),
ge_resolve
(
tup
,
rhs
)))
{
return
lhs
.
m_args
.
first
(
ge_resolve
(
tup
,
lhs
.
m_args
.
second
),
ge_resolve
(
tup
,
rhs
));
}
};
template
<
class
Tuple
,
typename
First
,
typename
Second
>
struct
ge_eval_
<
exec_fun3_op
,
Tuple
,
First
,
Second
>
{
static
inline
auto
_
(
Tuple
const
&
tup
,
First
const
&
lhs
,
Second
const
&
rhs
)
->
decltype
(
lhs
.
m_args
.
first
(
ge_resolve
(
tup
,
lhs
.
m_args
.
second
),
ge_resolve
(
tup
,
rhs
.
m_args
.
first
),
ge_resolve
(
tup
,
rhs
.
m_args
.
second
)))
{
return
lhs
.
m_args
.
first
(
ge_resolve
(
tup
,
lhs
.
m_args
.
second
),
ge_resolve
(
tup
,
rhs
.
m_args
.
first
),
ge_resolve
(
tup
,
rhs
.
m_args
.
second
));
}
};
template
<
operator_id
OP
,
class
Tuple
,
typename
First
,
typename
Second
>
inline
typename
ge_result
<
OP
,
First
,
Second
,
Tuple
>::
type
ge_eval
(
Tuple
const
&
tup
,
First
const
&
lhs
,
Second
const
&
rhs
)
{
return
ge_eval_
<
OP
,
Tuple
,
First
,
Second
>::
_
(
tup
,
lhs
,
rhs
);
}
template
<
class
Tuple
,
operator_id
OP
,
typename
First
,
typename
Second
>
auto
ge_resolve
(
Tuple
const
&
tup
,
guard_expr
<
OP
,
First
,
Second
>
const
&
ge
)
->
typename
ge_result
<
OP
,
First
,
Second
,
Tuple
>::
type
{
return
ge_eval
<
OP
>
(
tup
,
ge
.
m_args
.
first
,
ge
.
m_args
.
second
);
}
template
<
operator_id
OP
,
typename
First
,
typename
Second
,
typename
...
Args
>
auto
ge_invoke_step2
(
guard_expr
<
OP
,
First
,
Second
>
const
&
ge
,
detail
::
tdata
<
Args
...
>
const
&
tup
)
->
typename
ge_result
<
OP
,
First
,
Second
,
detail
::
tdata
<
Args
...
>>::
type
{
return
ge_eval
<
OP
>
(
tup
,
ge
.
m_args
.
first
,
ge
.
m_args
.
second
);
}
template
<
operator_id
OP
,
typename
First
,
typename
Second
,
typename
...
Args
>
auto
ge_invoke
(
guard_expr
<
OP
,
First
,
Second
>
const
&
ge
,
Args
const
&
...
args
)
->
typename
ge_result
<
OP
,
First
,
Second
,
detail
::
tdata
<
Args
*
...
>>::
type
{
detail
::
tdata
<
Args
const
*
...
>
tup
{
&
args
...};
return
ge_invoke_step2
(
ge
,
tup
);
}
template
<
class
GuardExpr
>
struct
ge_invoke_helper
{
GuardExpr
const
&
ge
;
ge_invoke_helper
(
GuardExpr
const
&
arg
)
:
ge
(
arg
)
{
}
template
<
typename
...
Args
>
bool
operator
()(
Args
&&
...
args
)
{
return
ge_invoke
(
ge
,
std
::
forward
<
Args
>
(
args
)...);
}
};
template
<
typename
TupleTypes
,
operator_id
OP
,
typename
First
,
typename
Second
>
typename
ge_result
<
OP
,
First
,
Second
,
typename
detail
::
tdata_from_type_list
<
typename
util
::
tl_filter_not
<
TupleTypes
,
is_anything
>::
type
>::
type
>::
type
ge_invoke_any
(
guard_expr
<
OP
,
First
,
Second
>
const
&
ge
,
any_tuple
const
&
tup
)
{
typedef
typename
ge_result
<
OP
,
First
,
Second
,
typename
detail
::
tdata_from_type_list
<
typename
util
::
tl_filter_not
<
TupleTypes
,
is_anything
>::
type
>::
type
>::
type
result_type
;
using
namespace
util
;
typename
if_else
<
std
::
is_same
<
typename
TupleTypes
::
back
,
anything
>
,
TupleTypes
,
wrapped
<
typename
tl_push_back
<
TupleTypes
,
anything
>::
type
>
>::
type
cast_token
;
auto
x
=
tuple_cast
(
tup
,
cast_token
);
CPPA_REQUIRE
(
static_cast
<
bool
>
(
x
)
==
true
);
ge_invoke_helper
<
guard_expr
<
OP
,
First
,
Second
>
>
f
{
ge
};
return
util
::
unchecked_apply_tuple
<
result_type
>
(
f
,
*
x
);
}
// finally ...
namespace
placeholders
{
namespace
{
constexpr
guard_placeholder
<
0
>
_x1
;
constexpr
guard_placeholder
<
1
>
_x2
;
constexpr
guard_placeholder
<
2
>
_x3
;
constexpr
guard_placeholder
<
3
>
_x4
;
constexpr
guard_placeholder
<
4
>
_x5
;
constexpr
guard_placeholder
<
5
>
_x6
;
constexpr
guard_placeholder
<
6
>
_x7
;
constexpr
guard_placeholder
<
7
>
_x8
;
constexpr
guard_placeholder
<
8
>
_x9
;
}
}
// namespace placeholders::<anonymous>
}
// namespace cppa
#endif // GUARD_EXPR_HPP
cppa/on.hpp
View file @
00f15911
...
@@ -39,6 +39,7 @@
...
@@ -39,6 +39,7 @@
#include "cppa/anything.hpp"
#include "cppa/anything.hpp"
#include "cppa/behavior.hpp"
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/guard_expr.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/util/duration.hpp"
...
@@ -98,7 +99,9 @@ class rvalue_builder
...
@@ -98,7 +99,9 @@ class rvalue_builder
typedef
typename
pattern_from_type_list
<
types
>::
type
pattern_type
;
typedef
typename
pattern_from_type_list
<
types
>::
type
pattern_type
;
std
::
unique_ptr
<
value_matcher
>
m_vm
;
typedef
std
::
unique_ptr
<
value_matcher
>
vm_ptr
;
vm_ptr
m_vm
;
template
<
typename
F
>
template
<
typename
F
>
partial_function
cr_rvalue
(
F
&&
f
,
std
::
integral_constant
<
bool
,
true
>
)
partial_function
cr_rvalue
(
F
&&
f
,
std
::
integral_constant
<
bool
,
true
>
)
...
@@ -123,6 +126,30 @@ class rvalue_builder
...
@@ -123,6 +126,30 @@ class rvalue_builder
public:
public:
template
<
operator_id
OP
,
typename
F
,
typename
S
>
rvalue_builder
&
when
(
guard_expr
<
OP
,
F
,
S
>
ge
)
{
typedef
guard_expr
<
OP
,
F
,
S
>
gtype
;
struct
vm_impl
:
value_matcher
{
vm_ptr
m_ptr
;
gtype
m_ge
;
vm_impl
(
vm_ptr
&&
ptr
,
gtype
&&
g
)
:
m_ptr
(
std
::
move
(
ptr
)),
m_ge
(
std
::
move
(
g
))
{
}
bool
operator
()(
any_tuple
const
&
tup
)
const
{
static_assert
(
std
::
is_same
<
decltype
(
ge_invoke_any
<
types
>
(
m_ge
,
tup
)),
bool
>::
value
,
"guard expression does not return a boolean"
);
if
((
*
m_ptr
)(
tup
))
{
return
ge_invoke_any
<
types
>
(
m_ge
,
tup
);
}
return
false
;
}
};
m_vm
.
reset
(
new
vm_impl
(
std
::
move
(
m_vm
),
std
::
move
(
ge
)));
return
*
this
;
}
template
<
typename
...
Args
>
template
<
typename
...
Args
>
rvalue_builder
(
Args
&&
...
args
)
rvalue_builder
(
Args
&&
...
args
)
:
m_vm
(
pattern_type
::
get_value_matcher
(
std
::
forward
<
Args
>
(
args
)...))
:
m_vm
(
pattern_type
::
get_value_matcher
(
std
::
forward
<
Args
>
(
args
)...))
...
...
cppa/util/apply_tuple.hpp
View file @
00f15911
...
@@ -82,8 +82,7 @@ struct apply_tuple_util<Result, IsManipulator, 1, 0>
...
@@ -82,8 +82,7 @@ struct apply_tuple_util<Result, IsManipulator, 1, 0>
};
};
template
<
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
template
<
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
auto
apply_tuple
(
F
&&
fun
,
Tuple
<
T
...
>&
tup
)
typename
get_result_type
<
F
>::
type
apply_tuple
(
F
&&
fun
,
Tuple
<
T
...
>&
tup
)
->
typename
get_result_type
<
F
>::
type
{
{
typedef
typename
get_result_type
<
F
>::
type
result_type
;
typedef
typename
get_result_type
<
F
>::
type
result_type
;
typedef
typename
get_arg_types
<
F
>::
types
fun_args
;
typedef
typename
get_arg_types
<
F
>::
types
fun_args
;
...
@@ -98,8 +97,7 @@ auto apply_tuple(F&& fun, Tuple<T...>& tup)
...
@@ -98,8 +97,7 @@ auto apply_tuple(F&& fun, Tuple<T...>& tup)
}
}
template
<
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
template
<
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
auto
apply_tuple
(
F
&&
fun
,
Tuple
<
T
...
>
const
&
tup
)
typename
get_result_type
<
F
>::
type
apply_tuple
(
F
&&
fun
,
Tuple
<
T
...
>
const
&
tup
)
->
typename
get_result_type
<
F
>::
type
{
{
typedef
typename
get_result_type
<
F
>::
type
result_type
;
typedef
typename
get_result_type
<
F
>::
type
result_type
;
typedef
typename
get_arg_types
<
F
>::
types
fun_args
;
typedef
typename
get_arg_types
<
F
>::
types
fun_args
;
...
@@ -113,16 +111,24 @@ auto apply_tuple(F&& fun, Tuple<T...> const& tup)
...
@@ -113,16 +111,24 @@ auto apply_tuple(F&& fun, Tuple<T...> const& tup)
::
apply
(
std
::
forward
<
F
>
(
fun
),
tup
);
::
apply
(
std
::
forward
<
F
>
(
fun
),
tup
);
}
}
template
<
typename
Result
,
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
template
<
typename
Result
,
size_t
From
,
size_t
To
,
Result
unchecked_apply_tuple
(
F
&&
fun
,
Tuple
<
T
...
>&
tup
)
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
Result
unchecked_apply_tuple_in_range
(
F
&&
fun
,
Tuple
<
T
...
>
const
&
tup
)
{
{
static
constexpr
size_t
tup_size
=
sizeof
...(
T
);
return
apply_tuple_util
<
Result
,
false
,
From
,
To
>
static
constexpr
size_t
from
=
0
;
static
constexpr
size_t
to
=
tup_size
-
1
;
return
apply_tuple_util
<
Result
,
false
,
from
,
to
>
::
apply
(
std
::
forward
<
F
>
(
fun
),
tup
);
::
apply
(
std
::
forward
<
F
>
(
fun
),
tup
);
}
}
// applies all values of @p tup to @p fun
// does not evaluate result type of functor
template
<
typename
Result
,
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
Result
unchecked_apply_tuple
(
F
&&
fun
,
Tuple
<
T
...
>
const
&
tup
)
{
return
unchecked_apply_tuple_in_range
<
Result
,
0
,
sizeof
...(
T
)
-
1
>
(
std
::
forward
<
F
>
(
fun
),
tup
);
}
}
}
// namespace cppa::util
}
}
// namespace cppa::util
#endif // APPLY_TUPLE_HPP
#endif // APPLY_TUPLE_HPP
cppa/util/type_list.hpp
View file @
00f15911
...
@@ -314,6 +314,20 @@ struct tl_concat<type_list<ListATypes...>, type_list<ListBTypes...> >
...
@@ -314,6 +314,20 @@ struct tl_concat<type_list<ListATypes...>, type_list<ListBTypes...> >
typedef
type_list
<
ListATypes
...,
ListBTypes
...
>
type
;
typedef
type_list
<
ListATypes
...,
ListBTypes
...
>
type
;
};
};
// list list::push_back(list, type)
template
<
typename
List
,
typename
What
>
struct
tl_push_back
;
/**
* @brief Appends @p What to given list.
*/
template
<
typename
...
ListTypes
,
typename
What
>
struct
tl_push_back
<
type_list
<
ListTypes
...
>
,
What
>
{
typedef
type_list
<
ListTypes
...,
What
>
type
;
};
// list list::appy(trait)
// list list::appy(trait)
template
<
typename
List
,
template
<
typename
>
class
Trait
>
template
<
typename
List
,
template
<
typename
>
class
Trait
>
...
...
unit_testing/test__match.cpp
View file @
00f15911
...
@@ -5,398 +5,110 @@
...
@@ -5,398 +5,110 @@
#include "cppa/match.hpp"
#include "cppa/match.hpp"
#include "cppa/announce.hpp"
#include "cppa/announce.hpp"
#include "cppa/to_string.hpp"
#include "cppa/to_string.hpp"
#include "cppa/guard_expr.hpp"
using
namespace
cppa
;
using
namespace
cppa
;
using
std
::
vector
;
using
std
::
vector
;
using
std
::
string
;
using
std
::
string
;
enum
operator_id
{
addition_op
,
subtraction_op
,
multiplication_op
,
division_op
,
modulo_op
,
less_op
,
less_eq_op
,
greater_op
,
greater_eq_op
,
equal_op
,
not_equal_op
,
exec_fun_op
,
logical_and_op
,
logical_or_op
};
#define CPPA_DISPATCH_OP(EnumValue, Operator) \
template<typename T1, typename T2> \
inline auto eval_op(std::integral_constant<operator_id, EnumValue >, \
T1 const& lhs, T2 const& rhs) const \
-> decltype(lhs Operator rhs) { return lhs Operator rhs; }
template
<
operator_id
,
typename
First
,
typename
Second
>
struct
guard_expr
;
template
<
int
X
>
struct
guard_placeholder
{
constexpr
guard_placeholder
()
{
}
template
<
typename
Fun
>
guard_expr
<
exec_fun_op
,
guard_placeholder
,
Fun
>
operator
()(
Fun
f
)
const
{
return
{
*
this
,
std
::
move
(
f
)};
}
};
template
<
operator_id
OP
,
typename
First
,
typename
Second
>
struct
guard_expr
;
template
<
typename
...
Ts
,
typename
T
>
T
const
&
fetch
(
detail
::
tdata
<
Ts
...
>
const
&
,
T
const
&
value
)
{
return
value
;
}
template
<
typename
...
Ts
,
int
X
>
auto
fetch
(
detail
::
tdata
<
Ts
...
>
const
&
tup
,
guard_placeholder
<
X
>
)
->
decltype
(
*
get
<
X
>
(
tup
))
{
return
*
get
<
X
>
(
tup
);
}
template
<
typename
...
Ts
,
operator_id
OP
,
typename
First
,
typename
Second
>
auto
fetch
(
detail
::
tdata
<
Ts
...
>
const
&
tup
,
guard_expr
<
OP
,
First
,
Second
>
const
&
ge
)
->
decltype
(
ge
.
eval
(
tup
));
template
<
class
Tuple
,
operator_id
OP
,
typename
First
,
typename
Second
>
auto
eval_guard_expr
(
std
::
integral_constant
<
operator_id
,
OP
>
token
,
Tuple
const
&
tup
,
First
const
&
lhs
,
Second
const
&
rhs
)
->
decltype
(
eval_op
(
token
,
fetch
(
tup
,
lhs
),
fetch
(
tup
,
rhs
)))
{
return
eval_op
(
token
,
fetch
(
tup
,
lhs
),
fetch
(
tup
,
rhs
));
}
template
<
class
Tuple
,
typename
First
,
typename
Second
>
bool
eval_guard_expr
(
std
::
integral_constant
<
operator_id
,
logical_and_op
>
,
Tuple
const
&
tup
,
First
const
&
lhs
,
Second
const
&
rhs
)
{
// emulate short-circuit evaluation
if
(
fetch
(
tup
,
lhs
))
return
fetch
(
tup
,
rhs
);
return
false
;
}
template
<
class
Tuple
,
typename
First
,
typename
Second
>
bool
eval_guard_expr
(
std
::
integral_constant
<
operator_id
,
logical_or_op
>
,
Tuple
const
&
tup
,
First
const
&
lhs
,
Second
const
&
rhs
)
{
// emulate short-circuit evaluation
if
(
fetch
(
tup
,
lhs
))
return
true
;
return
fetch
(
tup
,
rhs
);
}
template
<
typename
T
,
class
Tuple
>
struct
compute_
{
typedef
T
type
;
};
template
<
int
X
,
typename
...
Ts
>
struct
compute_
<
guard_placeholder
<
X
>
,
detail
::
tdata
<
Ts
...
>
>
{
typedef
typename
std
::
remove_pointer
<
typename
util
::
at
<
X
,
Ts
...
>::
type
>::
type
type
;
};
template
<
operator_id
OP
,
typename
First
,
typename
Second
,
class
Tuple
>
struct
compute_result_type
{
typedef
bool
type
;
};
template
<
typename
First
,
typename
Second
,
class
Tuple
>
struct
compute_result_type
<
addition_op
,
First
,
Second
,
Tuple
>
{
typedef
typename
compute_
<
First
,
Tuple
>::
type
lhs_type
;
typedef
typename
compute_
<
Second
,
Tuple
>::
type
rhs_type
;
typedef
decltype
(
lhs_type
()
+
rhs_type
())
type
;
};
template
<
operator_id
OP
,
typename
First
,
typename
Second
>
struct
guard_expr
{
std
::
pair
<
First
,
Second
>
m_args
;
template
<
typename
F
,
typename
S
>
guard_expr
(
F
&&
f
,
S
&&
s
)
:
m_args
(
std
::
forward
<
F
>
(
f
),
std
::
forward
<
S
>
(
s
))
{
}
guard_expr
()
=
default
;
guard_expr
(
guard_expr
&&
other
)
:
m_args
(
std
::
move
(
other
.
m_args
))
{
}
guard_expr
(
guard_expr
const
&
)
=
default
;
template
<
typename
...
Args
>
auto
eval
(
detail
::
tdata
<
Args
...
>
const
&
tup
)
const
->
typename
compute_result_type
<
OP
,
First
,
Second
,
detail
::
tdata
<
Args
...
>>::
type
{
std
::
integral_constant
<
operator_id
,
OP
>
token
;
return
eval_guard_expr
(
token
,
tup
,
m_args
.
first
,
m_args
.
second
);
}
template
<
typename
...
Args
>
auto
operator
()(
Args
const
&
...
args
)
const
->
typename
compute_result_type
<
OP
,
First
,
Second
,
detail
::
tdata
<
Args
...
>>::
type
{
detail
::
tdata
<
Args
const
*
...
>
tup
{
&
args
...};
return
eval
(
tup
);
}
};
template
<
typename
...
Ts
,
operator_id
OP
,
typename
First
,
typename
Second
>
auto
fetch
(
detail
::
tdata
<
Ts
...
>
const
&
tup
,
guard_expr
<
OP
,
First
,
Second
>
const
&
ge
)
->
decltype
(
ge
.
eval
(
tup
))
{
return
ge
.
eval
(
tup
);
}
static
constexpr
guard_placeholder
<
0
>
_x1
;
static
constexpr
guard_placeholder
<
1
>
_x2
;
static
constexpr
guard_placeholder
<
2
>
_x3
;
static
constexpr
guard_placeholder
<
3
>
_x4
;
static
constexpr
guard_placeholder
<
4
>
_x5
;
static
constexpr
guard_placeholder
<
5
>
_x6
;
static
constexpr
guard_placeholder
<
6
>
_x7
;
static
constexpr
guard_placeholder
<
7
>
_x8
;
static
constexpr
guard_placeholder
<
8
>
_x9
;
#define GUARD_PLACEHOLDER_OPERATOR(EnumValue, Operator) \
template<int Pos1, int Pos2> \
guard_expr< EnumValue , guard_placeholder<Pos1>, guard_placeholder<Pos2>> \
operator Operator (guard_placeholder<Pos1>, guard_placeholder<Pos2>) \
{ return {}; } \
template<int Pos, typename T> \
guard_expr< EnumValue , guard_placeholder<Pos>, \
typename detail::strip_and_convert<T>::type > \
operator Operator (guard_placeholder<Pos> gp, T value) \
{ return {std::move(gp), std::move(value)}; } \
template<typename T, int Pos> \
guard_expr< EnumValue , \
typename detail::strip_and_convert<T>::type, \
guard_placeholder<Pos> > \
operator Operator (T value, guard_placeholder<Pos> gp) \
{ return {std::move(value), std::move(gp)}; }
GUARD_PLACEHOLDER_OPERATOR
(
addition_op
,
+
)
GUARD_PLACEHOLDER_OPERATOR
(
subtraction_op
,
-
)
GUARD_PLACEHOLDER_OPERATOR
(
multiplication_op
,
*
)
GUARD_PLACEHOLDER_OPERATOR
(
division_op
,
/
)
GUARD_PLACEHOLDER_OPERATOR
(
modulo_op
,
%
)
GUARD_PLACEHOLDER_OPERATOR
(
less_op
,
<
)
GUARD_PLACEHOLDER_OPERATOR
(
less_eq_op
,
<=
)
GUARD_PLACEHOLDER_OPERATOR
(
greater_op
,
>=
)
GUARD_PLACEHOLDER_OPERATOR
(
greater_eq_op
,
>=
)
GUARD_PLACEHOLDER_OPERATOR
(
equal_op
,
==
)
GUARD_PLACEHOLDER_OPERATOR
(
not_equal_op
,
!=
)
template
<
operator_id
OP1
,
typename
F1
,
typename
S1
,
operator_id
OP2
,
typename
F2
,
typename
S2
>
guard_expr
<
logical_and_op
,
guard_expr
<
OP1
,
F1
,
S1
>
,
guard_expr
<
OP2
,
F2
,
S2
>>
operator
&&
(
guard_expr
<
OP1
,
F1
,
S1
>
lhs
,
guard_expr
<
OP2
,
F2
,
S2
>
rhs
)
{
return
{
std
::
move
(
lhs
),
std
::
move
(
rhs
)};
}
template
<
operator_id
OP1
,
typename
F1
,
typename
S1
,
operator_id
OP2
,
typename
F2
,
typename
S2
>
guard_expr
<
logical_or_op
,
guard_expr
<
OP1
,
F1
,
S1
>
,
guard_expr
<
OP2
,
F2
,
S2
>>
operator
||
(
guard_expr
<
OP1
,
F1
,
S1
>
lhs
,
guard_expr
<
OP2
,
F2
,
S2
>
rhs
)
{
return
{
std
::
move
(
lhs
),
std
::
move
(
rhs
)};
}
template
<
operator_id
OP
,
typename
F
,
typename
S
,
typename
T
>
guard_expr
<
equal_op
,
guard_expr
<
OP
,
F
,
S
>
,
T
>
operator
==
(
guard_expr
<
OP
,
F
,
S
>
lhs
,
T
rhs
)
{
return
{
std
::
move
(
lhs
),
std
::
move
(
rhs
)};
}
template
<
typename
TupleTypes
,
class
Fun
>
bool
eval_
(
any_tuple
const
&
tup
,
Fun
const
&
fun
)
{
typename
util
::
tl_concat
<
TupleTypes
,
util
::
type_list
<
anything
>>::
type
cast_token
;
auto
x
=
tuple_cast
(
tup
,
cast_token
);
CPPA_REQUIRE
(
static_cast
<
bool
>
(
x
)
==
true
);
return
util
::
unchecked_apply_tuple
<
bool
>
(
fun
,
*
x
);
}
template
<
class
GuardExpr
,
class
TupleTypes
>
struct
guard_expr_value_matcher
:
value_matcher
{
GuardExpr
m_expr
;
guard_expr_value_matcher
(
GuardExpr
&&
ge
)
:
m_expr
(
std
::
move
(
ge
))
{
}
bool
operator
()(
any_tuple
const
&
tup
)
const
{
typename
util
::
tl_concat
<
TupleTypes
,
util
::
type_list
<
anything
>>::
type
cast_token
;
auto
x
=
tuple_cast
(
tup
,
cast_token
);
CPPA_REQUIRE
(
static_cast
<
bool
>
(
x
)
==
true
);
return
util
::
unchecked_apply_tuple
<
bool
>
(
m_expr
,
*
x
);
}
};
bool
is_even
(
int
i
)
{
return
i
%
2
==
0
;
}
bool
is_even
(
int
i
)
{
return
i
%
2
==
0
;
}
struct
foobaz
{
template
<
typename
...
Args
>
bool
operator
()(
Args
const
&
...
args
)
{
detail
::
tdata
<
Args
const
*
...
>
tup
{
&
args
...};
cout
<<
"0: "
<<
fetch
(
tup
,
_x1
)
<<
endl
;
return
true
;
}
};
template
<
operator_id
OP
,
typename
First
,
typename
Second
>
value_matcher
*
when
(
guard_expr
<
OP
,
First
,
Second
>
ge
)
{
return
nullptr
;
}
std
::
string
to_string
(
operator_id
op
)
{
switch
(
op
)
{
case
addition_op
:
return
"+"
;
case
less_op
:
return
"<"
;
case
less_eq_op
:
return
"<="
;
case
greater_op
:
return
">"
;
case
greater_eq_op
:
return
">="
;
case
equal_op
:
return
"=="
;
case
not_equal_op
:
return
"!="
;
case
logical_and_op
:
return
"&&"
;
case
logical_or_op
:
return
"||"
;
default:
return
"???"
;
}
}
/*
template<typename T>
std::string to_string(T const& value)
{
std::ostringstream oss;
oss << value;
return oss.str();
}
*/
template
<
int
X
>
std
::
string
to_string
(
guard_placeholder
<
X
>
)
{
return
"_x"
+
std
::
to_string
(
X
+
1
);
}
template
<
typename
...
Ts
,
operator_id
OP
,
typename
First
,
typename
Second
>
std
::
string
to_string
(
guard_expr
<
OP
,
First
,
Second
>
const
&
ge
)
{
std
::
string
result
;
result
+=
"("
;
result
+=
to_string
(
ge
.
m_args
.
first
);
result
+=
to_string
(
OP
);
result
+=
to_string
(
ge
.
m_args
.
second
);
result
+=
")"
;
return
result
;
}
/*
/*
*
*
* projection:
* projection:
*
*
* on(_x.rsplit("--(.*)=(.*)")) >> [](std::vector<std::string> matched_groups)
{ }
* on(_x.rsplit("--(.*)=(.*)")) >> [](std::vector<std::string> matched_groups)
*
*
*/
*/
bool
ascending
(
int
a
,
int
b
,
int
c
)
{
return
a
<
b
&&
b
<
c
;
}
size_t
test__match
()
size_t
test__match
()
{
{
CPPA_TEST
(
test__match
);
CPPA_TEST
(
test__match
);
using
namespace
std
::
placeholders
;
using
namespace
std
::
placeholders
;
using
namespace
cppa
::
placeholders
;
foobaz
fb
;
auto
expr0
=
gbind
(
ascending
,
_x1
,
_x2
,
_x3
);
fb
(
1
);
CPPA_CHECK
(
ge_invoke
(
expr0
,
1
,
2
,
3
));
CPPA_CHECK
(
!
ge_invoke
(
expr0
,
3
,
2
,
1
));
typedef
util
::
type_list
<
int
,
int
,
int
,
int
>
ttypes
;
int
ival0
=
2
;
any_tuple
testee
=
make_cow_tuple
(
10
,
20
,
30
,
40
);
auto
expr01
=
gbind
(
ascending
,
_x1
,
std
::
ref
(
ival0
),
_x2
);
cout
<<
"testee[0] < testee[1] = "
CPPA_CHECK
(
ge_invoke
(
expr01
,
1
,
3
));
<<
eval_
<
ttypes
>
(
testee
,
_x1
<
_x2
)
++
ival0
;
<<
" ---- > "
CPPA_CHECK
(
!
ge_invoke
(
expr01
,
1
,
3
));
<<
eval_
<
ttypes
>
(
testee
,
_x1
<
_x2
&&
_x2
<
50
&&
_x3
<
_x4
&&
_x4
==
40
)
<<
" ---- > "
<<
eval_
<
ttypes
>
(
testee
,
5
<
_x1
)
<<
"; is_even(10): "
<<
eval_
<
ttypes
>
(
testee
,
_x1
(
is_even
))
<<
"; _x1 + _x2 < _x3: "
<<
eval_
<
ttypes
>
(
testee
,
_x1
+
_x2
<
_x3
)
<<
endl
;
auto
crazy_shit1
=
_x1
<
_x2
&&
_x2
<
50
&&
_x3
<
_x4
&&
_x4
==
40
;
auto
crazy_shit2
=
_x1
<
_x2
&&
(
_x2
<
50
&&
_x3
<
_x4
&&
_x4
==
40
);
cout
<<
to_string
(
crazy_shit1
)
<<
endl
;
cout
<<
to_string
(
crazy_shit2
)
<<
endl
;
auto
expr1
=
_x1
+
_x2
;
auto
expr1
=
_x1
+
_x2
;
auto
expr2
=
_x1
+
_x2
<
_x3
;
auto
expr2
=
_x1
+
_x2
<
_x3
;
auto
expr3
=
_x1
%
_x2
==
0
;
auto
expr3
=
_x1
%
_x2
==
0
;
CPPA_CHECK_EQUAL
(
5
,
(
expr1
(
2
,
3
)));
CPPA_CHECK_EQUAL
(
5
,
(
ge_invoke
(
expr1
,
2
,
3
)));
CPPA_CHECK
_EQUAL
(
"12"
,
(
expr1
(
std
::
string
{
"1"
},
std
::
string
{
"2"
})
));
CPPA_CHECK
(
ge_invoke
(
expr2
,
1
,
2
,
4
));
CPPA_CHECK_EQUAL
(
"
((_x1+_x2)<_x3)"
,
to_string
(
expr2
));
CPPA_CHECK_EQUAL
(
"
12"
,
(
ge_invoke
(
expr1
,
std
::
string
{
"1"
},
std
::
string
{
"2"
})
));
CPPA_CHECK
((
expr3
(
100
,
2
)));
CPPA_CHECK
((
ge_invoke
(
expr3
,
100
,
2
)));
auto
expr4
=
_x1
==
"-h"
||
_x1
==
"--help"
;
auto
expr4
=
_x1
==
"-h"
||
_x1
==
"--help"
;
CPPA_CHECK
(
expr4
(
std
::
string
(
"-h"
)));
CPPA_CHECK
(
ge_invoke
(
expr4
,
string
(
"-h"
)));
CPPA_CHECK
(
expr4
(
std
::
string
(
"--help"
)));
CPPA_CHECK
(
ge_invoke
(
expr4
,
string
(
"--help"
)));
CPPA_CHECK
(
!
expr4
(
std
::
string
(
"-g"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr4
,
string
(
"-g"
)));
exit
(
0
);
auto
expr5
=
_x1
.
starts_with
(
"--"
);
CPPA_CHECK
(
ge_invoke
(
expr5
,
string
(
"--help"
)));
/*
CPPA_CHECK
(
!
ge_invoke
(
expr5
,
string
(
"-help"
)));
auto xfun = _x.any_of<int>({1, 2, 3});
cout << "xfun(4) = " << xfun(4) << endl;
vector
<
string
>
vec1
{
"hello"
,
"world"
};
cout << "xfun(2) = " << xfun(2) << endl;
auto
expr6
=
_x1
.
in
(
vec1
);
CPPA_CHECK
(
ge_invoke
(
expr6
,
string
(
"hello"
)));
auto lfun = _x < 5;
CPPA_CHECK
(
ge_invoke
(
expr6
,
string
(
"world"
)));
cout << "lfun(4) = " << lfun(4) << endl;
CPPA_CHECK
(
!
ge_invoke
(
expr6
,
string
(
"hello world"
)));
cout << "lfun(6) = " << lfun(6) << endl;
auto
expr7
=
_x1
.
in
(
std
::
ref
(
vec1
));
CPPA_CHECK
(
ge_invoke
(
expr7
,
string
(
"hello"
)));
cout << "sizeof(std::function<bool (int const&)>) = "
CPPA_CHECK
(
ge_invoke
(
expr7
,
string
(
"world"
)));
<< sizeof(std::function<bool (int const&)>)
CPPA_CHECK
(
!
ge_invoke
(
expr7
,
string
(
"hello world"
)));
<< endl;
vec1
.
emplace_back
(
"hello world"
);
CPPA_CHECK
(
!
ge_invoke
(
expr6
,
string
(
"hello world"
)));
_on(_x.any_of({"-h", "--help"}), _x == 5);
CPPA_CHECK
(
ge_invoke
(
expr7
,
string
(
"hello world"
)));
auto hfun = _x.any_of({"-h", "--help"});
int
ival
=
5
;
cout << "hfun(-h) = " << hfun("-h") << endl;
auto
expr8
=
_x1
==
ival
;
cout << "hfun(-r) = " << hfun("-r") << endl;
auto
expr9
=
_x1
==
std
::
ref
(
ival
);
*/
CPPA_CHECK
(
ge_invoke
(
expr8
,
5
));
CPPA_CHECK
(
ge_invoke
(
expr9
,
5
));
ival
=
10
;
CPPA_CHECK
(
!
ge_invoke
(
expr9
,
5
));
CPPA_CHECK
(
ge_invoke
(
expr9
,
10
));
auto
expr11
=
_x1
.
in
({
"one"
,
"two"
});
CPPA_CHECK
(
ge_invoke
(
expr11
,
string
(
"one"
)));
CPPA_CHECK
(
ge_invoke
(
expr11
,
string
(
"two"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr11
,
string
(
"three"
)));
auto
expr12
=
_x1
*
_x2
<
_x3
-
_x4
;
CPPA_CHECK
(
ge_invoke
(
expr12
,
1
,
1
,
4
,
2
));
auto
expr13
=
_x1
.
not_in
({
"hello"
,
"world"
});
CPPA_CHECK
(
ge_invoke
(
expr13
,
string
(
"foo"
)));
CPPA_CHECK
(
!
ge_invoke
(
expr13
,
string
(
"hello"
)));
auto
expr14
=
_x1
+
_x2
;
static_assert
(
std
::
is_same
<
decltype
(
ge_invoke
(
expr14
,
1
,
2
)),
int
>::
value
,
"wrong return type"
);
CPPA_CHECK_EQUAL
(
5
,
(
ge_invoke
(
expr14
,
2
,
3
)));
auto
expr15
=
_x1
+
_x2
+
_x3
;
static_assert
(
std
::
is_same
<
decltype
(
ge_invoke
(
expr15
,
1
,
2
,
3
)),
int
>::
value
,
"wrong return type"
);
CPPA_CHECK_EQUAL
(
42
,
(
ge_invoke
(
expr15
,
7
,
10
,
25
)));
bool
invoked
=
false
;
bool
invoked
=
false
;
match
(
"abc"
)
match
(
"abc"
)
(
(
on
(
"abc"
)
>>
[
&
]()
on
<
string
>
().
when
(
_x1
==
"abc"
)
>>
[
&
]()
{
{
invoked
=
true
;
invoked
=
true
;
}
}
...
@@ -404,37 +116,60 @@ size_t test__match()
...
@@ -404,37 +116,60 @@ size_t test__match()
if
(
!
invoked
)
{
CPPA_ERROR
(
"match(
\"
abc
\"
) failed"
);
}
if
(
!
invoked
)
{
CPPA_ERROR
(
"match(
\"
abc
\"
) failed"
);
}
invoked
=
false
;
invoked
=
false
;
match
_each
({
"-h"
,
"-wtf"
})
match
(
std
::
vector
<
int
>
{
1
,
2
,
3
})
(
(
on
(
_x
.
any_of
({
"-h"
,
"--help"
}))
>>
[]()
on
<
int
,
int
,
int
>
().
when
(
_x1
+
_x2
+
_x3
==
6
&&
_x2
(
is_even
)
&&
_x3
%
2
==
1
)
>>
[
&
]()
{
{
cout
<<
"AWESOME!!!"
<<
endl
;
invoked
=
true
;
}
);
if
(
!
invoked
)
{
CPPA_ERROR
(
"match({1, 2, 3}) failed"
);
}
invoked
=
false
;
string
sum
;
match_each
({
"-h"
,
"--version"
,
"-wtf"
})
(
on
<
string
>
().
when
(
_x1
.
in
({
"-h"
,
"--help"
}))
>>
[
&
](
string
s
)
{
sum
+=
s
;
},
},
on
(
_x
.
starts_with
(
"-"
))
>>
[](
std
::
string
const
&
str
)
on
<
string
>
().
when
(
_x1
==
"-v"
||
_x1
==
"--version"
)
>>
[
&
](
string
s
)
{
sum
+=
s
;
},
on
<
string
>
().
when
(
_x1
.
starts_with
(
"-"
))
>>
[
&
](
string
const
&
str
)
{
{
match_each
(
str
.
begin
()
+
1
,
str
.
end
())
match_each
(
str
.
begin
()
+
1
,
str
.
end
())
(
(
on
<
char
>
()
>>
[](
char
c
)
on
<
char
>
().
when
(
_x1
.
in
({
'w'
,
't'
,
'f'
}))
>>
[
&
](
char
c
)
//on(_x.any_of({'w', 't', 'f'})) >> [](char c)
{
{
cout
<<
c
;
sum
+=
c
;
},
},
others
()
>>
[
](
any_tuple
const
&
tup
)
others
()
>>
[
&
](
)
{
{
cout
<<
"oops: "
<<
to_string
(
tup
)
<<
endl
;
CPPA_ERROR
(
"unexpected match"
)
;
}
}
);
);
cout
<<
endl
;
},
others
()
>>
[
&
]()
{
CPPA_ERROR
(
"unexpected match"
);
}
}
);
);
CPPA_CHECK_EQUAL
(
"-h--versionwtf"
,
sum
);
match
(
5
)
match
(
5
)
(
(
on
(
_x
<
6
)
>>
[
](
int
i
)
on
<
int
>
().
when
(
_x1
<
6
)
>>
[
&
](
int
i
)
{
{
cout
<<
i
<<
" < 6 !!! :)"
<<
endl
;
CPPA_CHECK_EQUAL
(
5
,
i
);
invoked
=
true
;
}
}
);
);
CPPA_CHECK
(
invoked
);
invoked
=
false
;
vector
<
string
>
vec
{
"a"
,
"b"
,
"c"
};
vector
<
string
>
vec
{
"a"
,
"b"
,
"c"
};
match
(
vec
)
match
(
vec
)
...
...
unit_testing/test__spawn.cpp
View file @
00f15911
...
@@ -23,7 +23,7 @@ using std::endl;
...
@@ -23,7 +23,7 @@ using std::endl;
using
namespace
cppa
;
using
namespace
cppa
;
// GCC 4.7 supports non-static member initialization
// GCC 4.7 supports non-static member initialization
#if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 7)
#if
0 //
(__GNUC__ >= 4) && (__GNUC_MINOR__ >= 7)
struct event_testee : public fsm_actor<event_testee>
struct event_testee : public fsm_actor<event_testee>
{
{
...
...
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