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
ee62b236
Commit
ee62b236
authored
Apr 05, 2012
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
guards
parent
cdd9aa4d
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
470 additions
and
84 deletions
+470
-84
cppa/on.hpp
cppa/on.hpp
+8
-11
cppa/pattern.hpp
cppa/pattern.hpp
+6
-6
cppa/util/apply_tuple.hpp
cppa/util/apply_tuple.hpp
+34
-16
cppa/util/static_foreach.hpp
cppa/util/static_foreach.hpp
+10
-0
src/pattern.cpp
src/pattern.cpp
+1
-1
unit_testing/test__match.cpp
unit_testing/test__match.cpp
+411
-50
No files found.
cppa/on.hpp
View file @
ee62b236
...
...
@@ -80,7 +80,9 @@ class rvalue_builder
typedef
util
::
arg_match_t
arg_match_t
;
typedef
util
::
type_list
<
TypeList
...
>
raw_types
;
typedef
util
::
type_list
<
typename
detail
::
implicit_conversions
<
TypeList
>::
type
...
>
raw_types
;
static
constexpr
bool
is_complete
=
!
std
::
is_same
<
arg_match_t
,
typename
raw_types
::
back
>::
value
;
...
...
@@ -94,12 +96,7 @@ class rvalue_builder
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
<
types
,
detail
::
implicit_conversions
>::
type
converted_types
;
typedef
typename
pattern_from_type_list
<
converted_types
>::
type
pattern_type
;
typedef
typename
pattern_from_type_list
<
types
>::
type
pattern_type
;
std
::
unique_ptr
<
value_matcher
>
m_vm
;
...
...
@@ -115,11 +112,11 @@ class rvalue_builder
{
using
namespace
::
cppa
::
util
;
typedef
typename
get_callable_trait
<
F
>::
type
ctrait
;
typedef
typename
ctrait
::
arg_types
raw_types
;
typedef
typename
ctrait
::
arg_types
raw_
arg_
types
;
static_assert
(
raw_types
::
size
>
0
,
"functor has no arguments"
);
typedef
typename
tl_apply
<
raw_
types
,
rm_ref
>::
type
new
_types
;
typedef
typename
tl_concat
<
converted_types
,
new_types
>::
type
types
;
typedef
typename
pattern_from_type_list
<
types
>::
type
epattern
;
typedef
typename
tl_apply
<
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
));
}
...
...
cppa/pattern.hpp
View file @
ee62b236
...
...
@@ -87,13 +87,13 @@ struct value_matcher
const
bool
is_dummy
;
inline
value_matcher
(
bool
dummy_impl
=
false
)
:
is_dummy
(
dummy_impl
)
{
}
virtual
~
value_matcher
();
virtual
bool
operator
()(
any_tuple
const
&
)
=
0
;
virtual
bool
operator
()(
any_tuple
const
&
)
const
=
0
;
};
struct
dummy_matcher
:
value_matcher
{
inline
dummy_matcher
()
:
value_matcher
(
true
)
{
}
bool
operator
()(
any_tuple
const
&
);
bool
operator
()(
any_tuple
const
&
)
const
;
};
struct
cmp_helper
...
...
@@ -135,7 +135,7 @@ class value_matcher_impl<wildcard_position::nil,
template
<
typename
...
Args
>
value_matcher_impl
(
Args
&&
...
args
)
:
m_values
(
std
::
forward
<
Args
>
(
args
)...)
{
}
bool
operator
()(
any_tuple
const
&
tup
)
bool
operator
()(
any_tuple
const
&
tup
)
const
{
cmp_helper
h
{
tup
};
return
util
::
static_foreach
<
0
,
sizeof
...(
Vs
)
>::
eval
(
m_values
,
h
);
...
...
@@ -177,7 +177,7 @@ class value_matcher_impl<wildcard_position::leading,
template
<
typename
...
Args
>
value_matcher_impl
(
Args
&&
...
args
)
:
m_values
(
std
::
forward
<
Args
>
(
args
)...)
{
}
bool
operator
()(
any_tuple
const
&
tup
)
bool
operator
()(
any_tuple
const
&
tup
)
const
{
cmp_helper
h
{
tup
,
tup
.
size
()
-
sizeof
...(
Ts
)};
return
util
::
static_foreach
<
0
,
sizeof
...(
Vs
)
>::
eval
(
m_values
,
h
);
...
...
@@ -198,7 +198,7 @@ class value_matcher_impl<wildcard_position::in_between,
template
<
typename
...
Args
>
value_matcher_impl
(
Args
&&
...
args
)
:
m_values
(
std
::
forward
<
Args
>
(
args
)...)
{
}
bool
operator
()(
any_tuple
const
&
tup
)
bool
operator
()(
any_tuple
const
&
tup
)
const
{
static
constexpr
size_t
wcpos
=
static_cast
<
size_t
>
(
util
::
tl_find
<
util
::
type_list
<
Ts
...
>
,
anything
>::
value
);
...
...
@@ -225,7 +225,7 @@ class value_matcher_impl<wildcard_position::multiple,
template
<
typename
...
Args
>
value_matcher_impl
(
Args
&&
...)
{
}
bool
operator
()(
any_tuple
const
&
)
bool
operator
()(
any_tuple
const
&
)
const
{
throw
std
::
runtime_error
(
"not implemented yet, sorry"
);
}
...
...
cppa/util/apply_tuple.hpp
View file @
ee62b236
...
...
@@ -31,6 +31,7 @@
#ifndef APPLY_TUPLE_HPP
#define APPLY_TUPLE_HPP
#include "cppa/get.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/is_manipulator.hpp"
...
...
@@ -38,40 +39,43 @@
namespace
cppa
{
namespace
util
{
template
<
size_t
...
Range
>
template
<
typename
Result
,
bool
IsManipulator
,
size_t
...
Range
>
struct
apply_tuple_impl
{
template
<
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
static
auto
apply
(
F
&&
f
,
Tuple
<
T
...
>
const
&
args
,
typename
disable_if
<
is_manipulator
<
F
>
,
int
>::
type
=
0
)
->
typename
get_result_type
<
F
>::
type
static
Result
apply
(
F
&&
f
,
Tuple
<
T
...
>
const
&
args
)
{
return
f
(
get
<
Range
>
(
args
)...);
}
};
template
<
typename
Result
,
size_t
...
Range
>
struct
apply_tuple_impl
<
Result
,
true
,
Range
...
>
{
template
<
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
static
auto
apply
(
F
&&
f
,
Tuple
<
T
...
>&
args
,
typename
enable_if
<
is_manipulator
<
F
>
,
int
>::
type
=
0
)
->
typename
get_result_type
<
F
>::
type
static
Result
apply
(
F
&&
f
,
Tuple
<
T
...
>&
args
)
{
return
f
(
get_ref
<
Range
>
(
args
)...);
}
};
template
<
int
From
,
int
To
,
int
...
Args
>
struct
apply_tuple_util
:
apply_tuple_util
<
From
,
To
-
1
,
To
,
Args
...
>
template
<
typename
Result
,
bool
IsManipulator
,
int
From
,
int
To
,
int
...
Args
>
struct
apply_tuple_util
:
apply_tuple_util
<
Result
,
IsManipulator
,
From
,
To
-
1
,
To
,
Args
...
>
{
};
template
<
int
X
,
int
...
Args
>
struct
apply_tuple_util
<
X
,
X
,
Args
...
>
:
apply_tuple_impl
<
X
,
Args
...
>
template
<
typename
Result
,
bool
IsManipulator
,
int
X
,
int
...
Args
>
struct
apply_tuple_util
<
Result
,
IsManipulator
,
X
,
X
,
Args
...
>
:
apply_tuple_impl
<
Result
,
IsManipulator
,
X
,
Args
...
>
{
};
template
<
>
struct
apply_tuple_util
<
1
,
0
>
template
<
typename
Result
,
bool
IsManipulator
>
struct
apply_tuple_util
<
Result
,
IsManipulator
,
1
,
0
>
{
template
<
typename
F
,
class
Unused
>
static
auto
apply
(
F
&&
f
,
Unused
const
&
)
->
typename
get_result_type
<
F
>::
type
static
Result
apply
(
F
&&
f
,
Unused
const
&
)
{
return
f
();
}
...
...
@@ -81,6 +85,7 @@ template<typename F, template<typename...> class Tuple, typename... T>
auto
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_arg_types
<
F
>::
types
fun_args
;
static
constexpr
size_t
tup_size
=
sizeof
...(
T
);
static_assert
(
tup_size
>=
fun_args
::
size
,
...
...
@@ -88,13 +93,15 @@ auto apply_tuple(F&& fun, Tuple<T...>& tup)
static
constexpr
size_t
args_size
=
fun_args
::
size
;
static
constexpr
size_t
from
=
(
args_size
>
0
)
?
tup_size
-
args_size
:
1
;
static
constexpr
size_t
to
=
(
args_size
>
0
)
?
tup_size
-
1
:
0
;
return
apply_tuple_util
<
from
,
to
>::
apply
(
std
::
forward
<
F
>
(
fun
),
tup
);
return
apply_tuple_util
<
result_type
,
is_manipulator
<
F
>::
value
,
from
,
to
>
::
apply
(
std
::
forward
<
F
>
(
fun
),
tup
);
}
template
<
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
auto
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_arg_types
<
F
>::
types
fun_args
;
static
constexpr
size_t
tup_size
=
sizeof
...(
T
);
static_assert
(
tup_size
>=
fun_args
::
size
,
...
...
@@ -102,7 +109,18 @@ auto apply_tuple(F&& fun, Tuple<T...> const& tup)
static
constexpr
size_t
args_size
=
fun_args
::
size
;
static
constexpr
size_t
from
=
(
args_size
>
0
)
?
tup_size
-
args_size
:
1
;
static
constexpr
size_t
to
=
(
args_size
>
0
)
?
tup_size
-
1
:
0
;
return
apply_tuple_util
<
from
,
to
>::
apply
(
std
::
forward
<
F
>
(
fun
),
tup
);
return
apply_tuple_util
<
result_type
,
is_manipulator
<
F
>::
value
,
from
,
to
>
::
apply
(
std
::
forward
<
F
>
(
fun
),
tup
);
}
template
<
typename
Result
,
typename
F
,
template
<
typename
...
>
class
Tuple
,
typename
...
T
>
Result
unchecked_apply_tuple
(
F
&&
fun
,
Tuple
<
T
...
>&
tup
)
{
static
constexpr
size_t
tup_size
=
sizeof
...(
T
);
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
);
}
}
}
// namespace cppa::util
...
...
cppa/util/static_foreach.hpp
View file @
ee62b236
...
...
@@ -50,6 +50,12 @@ struct static_foreach_impl
return
f
(
get
<
Begin
>
(
c
))
&&
static_foreach_impl
<
Begin
+
1
,
End
,
(
Begin
+
1
>
End
)
>::
eval
(
c
,
f
);
}
template
<
typename
Container
,
typename
Fun
>
static
inline
bool
eval_or
(
Container
const
&
c
,
Fun
&
f
)
{
return
f
(
get
<
Begin
>
(
c
))
||
static_foreach_impl
<
Begin
+
1
,
End
,
(
Begin
+
1
>
End
)
>::
eval_or
(
c
,
f
);
}
};
template
<
size_t
X
>
...
...
@@ -59,6 +65,8 @@ struct static_foreach_impl<X, X, false>
static
inline
void
_
(
Container
const
&
,
Fun
&
)
{
}
template
<
typename
Container
,
typename
Fun
>
static
inline
bool
eval
(
Container
const
&
,
Fun
&
)
{
return
true
;
}
template
<
typename
Container
,
typename
Fun
>
static
inline
bool
eval_or
(
Container
const
&
,
Fun
&
)
{
return
true
;
}
};
template
<
size_t
X
,
size_t
Y
>
...
...
@@ -68,6 +76,8 @@ struct static_foreach_impl<X, Y, true>
static
inline
void
_
(
Container
const
&
,
Fun
&
)
{
}
template
<
typename
Container
,
typename
Fun
>
static
inline
bool
eval
(
Container
const
&
,
Fun
&
)
{
return
true
;
}
template
<
typename
Container
,
typename
Fun
>
static
inline
bool
eval_or
(
Container
const
&
,
Fun
&
)
{
return
true
;
}
};
/**
...
...
src/pattern.cpp
View file @
ee62b236
...
...
@@ -34,7 +34,7 @@ namespace cppa {
value_matcher
::~
value_matcher
()
{
}
bool
dummy_matcher
::
operator
()(
any_tuple
const
&
)
bool
dummy_matcher
::
operator
()(
any_tuple
const
&
)
const
{
return
true
;
}
...
...
unit_testing/test__match.cpp
View file @
ee62b236
...
...
@@ -11,58 +11,13 @@ using namespace cppa;
using
std
::
vector
;
using
std
::
string
;
#define CPPA_GUARD_IMPL(GuardOperator) \
struct impl : util::guard<T> \
{ \
T m_val; \
impl(T&& val) : m_val(std::move(val)) { } \
bool operator()(T const& other) const { return other < m_val; } \
}; return std::unique_ptr<util::guard<T>>{new impl{std::move(value)}}
struct
pattern_placeholder
{
constexpr
pattern_placeholder
()
{
}
template
<
typename
T
>
std
::
unique_ptr
<
util
::
guard
<
T
>>
operator
<
(
T
value
)
const
{
CPPA_GUARD_IMPL
(
<
);
}
template
<
typename
T
>
std
::
unique_ptr
<
util
::
guard
<
T
>>
operator
<=
(
T
value
)
const
{
CPPA_GUARD_IMPL
(
<=
);
}
template
<
typename
T
>
std
::
unique_ptr
<
util
::
guard
<
T
>>
operator
>
(
T
value
)
const
{
CPPA_GUARD_IMPL
(
>
);
}
template
<
typename
T
>
std
::
unique_ptr
<
util
::
guard
<
T
>>
operator
>=
(
T
value
)
const
{
CPPA_GUARD_IMPL
(
>=
);
}
template
<
typename
T
>
T
operator
==
(
T
value
)
const
{
return
value
;
}
template
<
typename
T
>
std
::
unique_ptr
<
util
::
guard
<
T
>>
operator
!=
(
T
value
)
const
{
CPPA_GUARD_IMPL
(
!=
);
}
template
<
typename
T
>
std
::
unique_ptr
<
util
::
guard
<
T
>>
any_of
(
std
::
vector
<
T
>
vec
)
const
{
cout
<<
"guard<vector<"
<<
detail
::
demangle
(
typeid
(
T
).
name
())
<<
">>"
<<
endl
;
typedef
std
::
vector
<
T
>
vector_type
;
struct
impl
:
util
::
guard
<
T
>
{
...
...
@@ -70,7 +25,6 @@ cout << "guard<vector<" << detail::demangle(typeid(T).name()) << ">>" << endl;
impl
(
vector_type
&&
v
)
:
m_vec
(
std
::
move
(
v
))
{
}
bool
operator
()(
T
const
&
value
)
const
{
cout
<<
"guard<vector<"
<<
detail
::
demangle
(
typeid
(
T
).
name
())
<<
">>::operator()("
<<
value
<<
")"
<<
endl
;
return
std
::
any_of
(
m_vec
.
begin
(),
m_vec
.
end
(),
[
&
](
T
const
&
val
)
{
return
val
==
value
;
});
}
...
...
@@ -107,20 +61,428 @@ cout << "guard<vector<" << detail::demangle(typeid(T).name()) << ">>" << endl;
return
std
::
unique_ptr
<
util
::
guard
<
str_type
>>
{
new
impl
{
std
::
move
(
substr
)}};
}
};
#define CPPA_GUARD_OPERATOR(Operator) \
template<typename T> \
std::unique_ptr<util::guard<T> > \
operator Operator (pattern_placeholder const&, T value) { \
struct impl : util::guard<T> { \
T m_val; \
impl(T&& val) : m_val(std::move(val)) { } \
bool operator()(T const& other) const \
{ return other Operator m_val; } \
}; \
return std::unique_ptr<util::guard<T> >{new impl{std::move(value)}}; \
} \
template<typename T> \
std::unique_ptr<util::guard<T> > \
operator Operator (T value, pattern_placeholder const&) { \
struct impl : util::guard<T> { \
T m_val; \
impl(T&& val) : m_val(std::move(val)) { } \
bool operator()(T const& other) const \
{ return m_val Operator other; } \
}; \
return std::unique_ptr<util::guard<T> >{new impl{std::move(value)}}; \
}
CPPA_GUARD_OPERATOR
(
<
)
CPPA_GUARD_OPERATOR
(
<=
)
CPPA_GUARD_OPERATOR
(
>
)
CPPA_GUARD_OPERATOR
(
>=
)
CPPA_GUARD_OPERATOR
(
==
)
CPPA_GUARD_OPERATOR
(
!=
)
static
constexpr
pattern_placeholder
_x
;
template
<
typename
...
Args
>
void
_on
(
Args
&&
...)
enum
eval_op
{
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 operator()(std::integral_constant<eval_op, EnumValue >, \
T1 const& lhs, T2 const& rhs) const \
-> decltype(lhs Operator rhs) { return lhs Operator rhs; }
struct
op_dispatcher
{
constexpr
op_dispatcher
()
{
}
CPPA_DISPATCH_OP
(
addition_op
,
+
)
CPPA_DISPATCH_OP
(
subtraction_op
,
-
)
CPPA_DISPATCH_OP
(
multiplication_op
,
*
)
CPPA_DISPATCH_OP
(
division_op
,
/
)
CPPA_DISPATCH_OP
(
modulo_op
,
%
)
CPPA_DISPATCH_OP
(
less_op
,
<
)
CPPA_DISPATCH_OP
(
less_eq_op
,
<=
)
CPPA_DISPATCH_OP
(
greater_op
,
>
)
CPPA_DISPATCH_OP
(
greater_eq_op
,
>=
)
CPPA_DISPATCH_OP
(
equal_op
,
==
)
CPPA_DISPATCH_OP
(
not_equal_op
,
!=
)
template
<
typename
T
,
typename
Fun
>
inline
bool
operator
()(
std
::
integral_constant
<
eval_op
,
exec_fun_op
>
,
T
const
&
arg
,
Fun
const
&
fun
)
const
{
return
fun
(
arg
);
}
};
static
constexpr
op_dispatcher
s_opd
;
template
<
eval_op
,
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
<
eval_op
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
,
eval_op
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
,
eval_op
OP
,
typename
First
,
typename
Second
>
auto
eval_guard_expr
(
std
::
integral_constant
<
eval_op
,
OP
>
token
,
Tuple
const
&
tup
,
First
const
&
lhs
,
Second
const
&
rhs
)
->
decltype
(
s_opd
(
token
,
fetch
(
tup
,
lhs
),
fetch
(
tup
,
rhs
)))
{
return
s_opd
(
token
,
fetch
(
tup
,
lhs
),
fetch
(
tup
,
rhs
));
}
template
<
class
Tuple
,
typename
First
,
typename
Second
>
bool
eval_guard_expr
(
std
::
integral_constant
<
eval_op
,
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
<
eval_op
,
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
<
eval_op
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
<
eval_op
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
<
eval_op
,
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
,
eval_op
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
<
eval_op
OP1
,
typename
F1
,
typename
S1
,
eval_op
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
<
eval_op
OP1
,
typename
F1
,
typename
S1
,
eval_op
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
<
eval_op
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
;
}
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
<
eval_op
OP
,
typename
First
,
typename
Second
>
value_matcher
*
when
(
guard_expr
<
OP
,
First
,
Second
>
ge
)
{
return
nullptr
;
}
std
::
string
to_string
(
eval_op
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
,
eval_op
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:
*
* on(_x.rsplit("--(.*)=(.*)")) >> [](std::vector<std::string> matched_groups) { }
*
*/
size_t
test__match
()
{
CPPA_TEST
(
test__match
);
using
namespace
std
::
placeholders
;
foobaz
fb
;
fb
(
1
);
typedef
util
::
type_list
<
int
,
int
,
int
,
int
>
ttypes
;
any_tuple
testee
=
make_cow_tuple
(
10
,
20
,
30
,
40
);
cout
<<
"testee[0] < testee[1] = "
<<
eval_
<
ttypes
>
(
testee
,
_x1
<
_x2
)
<<
" ---- > "
<<
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
expr2
=
_x1
+
_x2
<
_x3
;
auto
expr3
=
_x1
%
_x2
==
0
;
CPPA_CHECK_EQUAL
(
5
,
(
expr1
(
2
,
3
)));
CPPA_CHECK_EQUAL
(
"12"
,
(
expr1
(
std
::
string
{
"1"
},
std
::
string
{
"2"
})));
CPPA_CHECK_EQUAL
(
"((_x1+_x2)<_x3)"
,
to_string
(
expr2
));
CPPA_CHECK
((
expr3
(
100
,
2
)));
auto
expr4
=
_x1
==
"-h"
||
_x1
==
"--help"
;
CPPA_CHECK
(
expr4
(
std
::
string
(
"-h"
)));
CPPA_CHECK
(
expr4
(
std
::
string
(
"--help"
)));
CPPA_CHECK
(
!
expr4
(
std
::
string
(
"-g"
)));
exit
(
0
);
/*
auto xfun = _x.any_of<int>({1, 2, 3});
cout << "xfun(4) = " << xfun(4) << endl;
...
...
@@ -174,7 +536,6 @@ size_t test__match()
);
cout
<<
endl
;
}
);
match
(
5
)
...
...
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