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
30bdfb6a
Commit
30bdfb6a
authored
Apr 09, 2012
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
pattern matching
parent
1620a761
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1210 additions
and
128 deletions
+1210
-128
Makefile.am
Makefile.am
+1
-0
cppa.files
cppa.files
+1
-0
cppa/detail/abstract_tuple.hpp
cppa/detail/abstract_tuple.hpp
+4
-0
cppa/detail/tdata.hpp
cppa/detail/tdata.hpp
+87
-63
cppa/detail/tuple_vals.hpp
cppa/detail/tuple_vals.hpp
+5
-0
cppa/guard_expr.hpp
cppa/guard_expr.hpp
+1
-0
cppa/util/callable_trait.hpp
cppa/util/callable_trait.hpp
+26
-0
cppa/util/static_foreach.hpp
cppa/util/static_foreach.hpp
+29
-32
cppa/util/type_list.hpp
cppa/util/type_list.hpp
+245
-18
cppa/util/type_pair.hpp
cppa/util/type_pair.hpp
+12
-0
cppa/util/void_type.hpp
cppa/util/void_type.hpp
+8
-0
src/abstract_tuple.cpp
src/abstract_tuple.cpp
+5
-0
unit_testing/test__tuple.cpp
unit_testing/test__tuple.cpp
+786
-15
No files found.
Makefile.am
View file @
30bdfb6a
...
...
@@ -176,6 +176,7 @@ nobase_library_include_HEADERS = \
cppa/tuple_cast.hpp
\
cppa/type_value_pair.hpp
\
cppa/uniform_type_info.hpp
\
cppa/util/a_matches_b.hpp
\
cppa/util/abstract_uniform_type_info.hpp
\
cppa/util/apply_tuple.hpp
\
cppa/util/arg_match_t.hpp
\
...
...
cppa.files
View file @
30bdfb6a
...
...
@@ -258,3 +258,4 @@ cppa/detail/matches.hpp
unit_testing/test__match.cpp
cppa/guard_expr.hpp
src/pattern.cpp
cppa/util/a_matches_b.hpp
cppa/detail/abstract_tuple.hpp
View file @
30bdfb6a
...
...
@@ -68,6 +68,10 @@ class abstract_tuple : public ref_counted
virtual
void
const
*
at
(
size_t
pos
)
const
=
0
;
virtual
uniform_type_info
const
*
type_at
(
size_t
pos
)
const
=
0
;
// returns either tdata<...> object or nullptr (default) if tuple
// is not a 'native' implementation
virtual
void
const
*
native_data
()
const
;
// Identifies the type of the implementation.
// A statically typed tuple implementation can use some optimizations,
// e.g., "impl_type() == statically_typed" implies that type_token()
...
...
cppa/detail/tdata.hpp
View file @
30bdfb6a
...
...
@@ -39,6 +39,8 @@
#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/abstract_tuple.hpp"
...
...
@@ -75,6 +77,13 @@ struct tdata<>
util
::
void_type
head
;
typedef
util
::
void_type
head_type
;
typedef
tdata
<>
tail_type
;
typedef
util
::
void_type
back_type
;
typedef
util
::
type_list
<>
types
;
static
constexpr
size_t
tdata_size
=
0
;
constexpr
tdata
()
{
}
inline
tdata
(
tdata
&&
)
{
}
...
...
@@ -84,15 +93,9 @@ struct tdata<>
// swallow "arg_match" silently
constexpr
tdata
(
util
::
wrapped
<
util
::
arg_match_t
>
const
&
)
{
}
tdata
<>&
tail
()
{
throw
std
::
out_of_range
(
""
);
}
tdata
<>&
tail
()
{
return
*
this
;
}
tdata
<>
const
&
tail
()
const
{
throw
std
::
out_of_range
(
""
);
}
tdata
<>
const
&
tail
()
const
{
return
*
this
;
}
inline
void
const
*
at
(
size_t
)
const
{
...
...
@@ -119,8 +122,22 @@ struct tdata<Head, Tail...> : tdata<Tail...>
typedef
tdata
<
Tail
...
>
super
;
typedef
util
::
type_list
<
Head
,
Tail
...
>
types
;
Head
head
;
static
constexpr
size_t
tdata_size
=
(
sizeof
...(
Tail
)
+
1
);
typedef
Head
head_type
;
typedef
tdata
<
Tail
...
>
tail_type
;
typedef
typename
util
::
if_else_c
<
(
sizeof
...(
Tail
)
>
0
),
typename
tdata
<
Tail
...
>::
back_type
,
util
::
wrapped
<
Head
>
>::
type
back_type
;
inline
tdata
()
:
super
(),
head
()
{
}
//tdata(Head const& v0, Tail const&... vals) : super(vals...), head(v0) { }
...
...
@@ -141,11 +158,51 @@ struct tdata<Head, Tail...> : tdata<Tail...>
}
// allow (partial) initialization from a different tdata
// with traling extra arguments to initialize additional arguments
template
<
typename
...
Y
>
tdata
(
tdata
<
Y
...
>
const
&
other
)
:
super
(
other
.
tail
()),
head
(
other
.
head
)
{
}
template
<
typename
...
Y
>
tdata
(
tdata
<
Y
...
>&&
other
)
:
super
(
std
::
move
(
other
.
tail
())),
head
(
std
::
move
(
other
.
head
))
{
}
template
<
typename
...
Y
>
tdata
(
tdata
<
Y
...
>
const
&
other
)
:
super
(
other
.
tail
()),
head
(
other
.
head
)
{
}
tdata
(
Head
const
&
arg
,
tdata
<
Y
...
>
const
&
other
)
:
super
(
other
),
head
(
arg
)
{
}
template
<
typename
...
Y
>
tdata
(
tdata
<
Y
...
>&&
other
)
:
super
(
std
::
move
(
other
.
tail
())),
head
(
std
::
move
(
other
.
head
))
{
}
tdata
(
tdata
<
Head
>
const
&
arg
,
tdata
<
Y
...
>
const
&
other
)
:
super
(
other
),
head
(
arg
.
head
)
{
}
template
<
typename
ExtraArg
,
typename
Y0
,
typename
Y1
,
typename
...
Y
>
tdata
(
tdata
<
Y0
,
Y1
,
Y
...
>
const
&
other
,
ExtraArg
const
&
arg
)
:
super
(
other
.
tail
(),
arg
),
head
(
other
.
head
)
{
}
template
<
typename
ExtraArg
,
typename
Y0
>
tdata
(
tdata
<
Y0
>
const
&
other
,
ExtraArg
const
&
arg
,
typename
util
::
enable_if_c
<
std
::
is_same
<
ExtraArg
,
ExtraArg
>::
value
&&
(
sizeof
...(
Tail
)
>
0
)
>::
type
*
=
0
)
:
super
(
arg
),
head
(
other
.
head
)
{
}
template
<
typename
ExtraArg
,
typename
Y0
>
tdata
(
tdata
<
Y0
>
const
&
other
,
ExtraArg
const
&
arg
,
typename
util
::
enable_if_c
<
std
::
is_same
<
ExtraArg
,
ExtraArg
>::
value
&&
(
sizeof
...(
Tail
)
==
0
)
>::
type
*
=
0
)
:
super
(),
head
(
other
.
head
,
arg
)
{
}
// allow initialization with a function pointer or reference
// returning a wrapped<Head>
...
...
@@ -183,75 +240,42 @@ struct tdata<Head, Tail...> : tdata<Tail...>
return
(
p
==
0
)
?
uniform_typeid
(
typeid
(
Head
))
:
super
::
type_at
(
p
-
1
);
}
};
template
<
typename
Head
,
typename
...
Tail
>
struct
tdata
<
option
<
Head
>
,
Tail
...
>
:
tdata
<
Tail
...
>
{
typedef
tdata
<
Tail
...
>
super
;
option
<
Head
>
head
;
typedef
option
<
Head
>
opt_type
;
inline
tdata
()
:
super
(),
head
()
{
}
template
<
typename
...
Args
>
tdata
(
Head
const
&
v0
,
Args
const
&
...
vals
)
:
super
(
vals
...),
head
(
v0
)
{
}
template
<
typename
...
Args
>
tdata
(
Head
&&
v0
,
Args
const
&
...
vals
)
:
super
(
vals
...),
head
(
std
::
move
(
v0
))
{
}
template
<
typename
...
Args
>
tdata
(
util
::
wrapped
<
Head
>
const
&
,
Args
const
&
...
vals
)
:
super
(
vals
...)
{
}
tdata
(
tdata
<>&&
)
:
super
(),
head
()
{
}
tdata
(
tdata
<>
const
&
)
:
super
(),
head
()
{
}
// allow (partial) initialization from a different tdata
template
<
typename
...
Y
>
tdata
(
tdata
<
Y
...
>
const
&
other
)
:
super
(
other
.
tail
()),
head
(
other
.
head
)
{
}
template
<
typename
...
Y
>
tdata
(
tdata
<
Y
...
>&&
other
)
:
super
(
std
::
move
(
other
.
tail
())),
head
(
std
::
move
(
other
.
head
))
{
}
// allow initialization with a function pointer or reference
// returning a wrapped<Head>
template
<
typename
...
Args
>
tdata
(
util
::
wrapped
<
Head
>
(
*
)(),
Args
const
&
...
vals
)
:
super
(
vals
...),
head
()
Head
&
_back
(
std
::
integral_constant
<
size_t
,
0
>
)
{
return
head
;
}
template
<
typename
Arg0
,
typename
...
Arg
s
>
inline
void
set
(
Arg0
&&
arg0
,
Args
&&
...
args
)
template
<
size_t
Po
s
>
back_type
&
_back
(
std
::
integral_constant
<
size_t
,
Pos
>
)
{
head
=
std
::
forward
<
Arg0
>
(
arg0
)
;
super
::
set
(
std
::
forward
<
Args
>
(
args
)...
);
std
::
integral_constant
<
size_t
,
Pos
-
1
>
token
;
return
super
::
_back
(
token
);
}
template
<
typename
...
Y
>
tdata
&
operator
=
(
tdata
<
Y
...
>
const
&
other
)
back_type
&
back
()
{
tdata_set
(
*
this
,
other
)
;
return
*
this
;
std
::
integral_constant
<
size_t
,
sizeof
...(
Tail
)
>
token
;
return
_back
(
token
)
;
}
// upcast
inline
tdata
<
Tail
...
>&
tail
()
{
return
*
this
;
}
inline
tdata
<
Tail
...
>
const
&
tail
()
const
{
return
*
this
;
}
inline
void
const
*
at
(
size_t
p
)
const
Head
const
&
_back
(
std
::
integral_constant
<
size_t
,
0
>
)
const
{
return
(
p
==
0
)
?
ptr_to
(
head
)
:
super
::
at
(
p
-
1
)
;
return
head
;
}
inline
uniform_type_info
const
*
type_at
(
size_t
p
)
const
template
<
size_t
Pos
>
back_type
const
&
_back
(
std
::
integral_constant
<
size_t
,
Pos
>
)
const
{
return
(
p
==
0
)
?
uniform_typeid
(
typeid
(
Head
))
:
super
::
type_at
(
p
-
1
);
std
::
integral_constant
<
size_t
,
Pos
-
1
>
token
;
return
super
::
_back
(
token
);
}
back_type
const
&
back
()
const
{
std
::
integral_constant
<
size_t
,
sizeof
...(
Tail
)
>
token
;
return
_back
(
token
);
}
};
template
<
typename
...
X
>
...
...
cppa/detail/tuple_vals.hpp
View file @
30bdfb6a
...
...
@@ -68,6 +68,11 @@ class tuple_vals : public abstract_tuple
{
}
void
const
*
native_data
()
const
{
return
&
m_data
;
}
inline
data_type
&
data
()
{
return
m_data
;
...
...
cppa/guard_expr.hpp
View file @
30bdfb6a
...
...
@@ -306,6 +306,7 @@ struct ge_reference_wrapper
{
T
const
*
value
;
ge_reference_wrapper
(
T
&&
)
=
delete
;
ge_reference_wrapper
()
:
value
(
nullptr
)
{
}
ge_reference_wrapper
(
T
const
&
val_ref
)
:
value
(
&
val_ref
)
{
}
ge_reference_wrapper
(
ge_reference_wrapper
const
&
)
=
default
;
ge_reference_wrapper
&
operator
=
(
ge_reference_wrapper
const
&
)
=
default
;
...
...
cppa/util/callable_trait.hpp
View file @
30bdfb6a
...
...
@@ -115,6 +115,32 @@ struct get_result_type
typedef
typename
trait_type
::
result_type
type
;
};
template
<
typename
T
>
struct
is_callable
{
template
<
typename
C
>
static
bool
_fun
(
C
*
,
typename
callable_trait
<
C
>::
result_type
*
=
nullptr
)
{
return
true
;
}
template
<
typename
C
>
static
bool
_fun
(
C
*
,
typename
callable_trait
<
decltype
(
&
C
::
operator
())
>::
result_type
*
=
nullptr
)
{
return
true
;
}
static
void
_fun
(
void
*
)
{
}
typedef
decltype
(
_fun
(
static_cast
<
T
*>
(
nullptr
)))
result_type
;
public:
static
constexpr
bool
value
=
std
::
is_same
<
bool
,
result_type
>::
value
;
};
}
}
// namespace cppa::util
#endif // CPPA_UTIL_CALLABLE_TRAIT
cppa/util/static_foreach.hpp
View file @
30bdfb6a
...
...
@@ -35,49 +35,46 @@
namespace
cppa
{
namespace
util
{
template
<
size_t
Begin
,
size_t
End
,
bool
BeginGreater
End
>
template
<
bool
BeginLessEnd
,
size_t
Begin
,
size_t
End
>
struct
static_foreach_impl
{
template
<
typename
Container
,
typename
Fun
>
static
inline
void
_
(
Container
const
&
c
,
Fun
&
f
)
template
<
typename
Container
,
typename
Fun
,
typename
...
Args
>
static
inline
void
_
(
Container
const
&
c
,
Fun
&
f
,
Args
const
&
...
args
)
{
f
(
get
<
Begin
>
(
c
));
static_foreach_impl
<
Begin
+
1
,
End
,
(
Begin
+
1
>
End
)
>::
_
(
c
,
f
);
f
(
get
<
Begin
>
(
c
)
,
args
...
);
static_foreach_impl
<
(
Begin
+
1
<
End
),
Begin
+
1
,
End
>::
_
(
c
,
f
,
args
...
);
}
template
<
typename
Container
,
typename
Fun
>
static
inline
bool
eval
(
Container
const
&
c
,
Fun
&
f
)
template
<
typename
Container
,
typename
Fun
,
typename
...
Args
>
static
inline
void
_ref
(
Container
&
c
,
Fun
&
f
,
Args
const
&
...
args
)
{
return
f
(
get
<
Begin
>
(
c
))
&&
static_foreach_impl
<
Begin
+
1
,
End
,
(
Begin
+
1
>
End
)
>::
eval
(
c
,
f
);
f
(
get_ref
<
Begin
>
(
c
),
args
...);
static_foreach_impl
<
(
Begin
+
1
<
End
),
Begin
+
1
,
End
>::
_ref
(
c
,
f
,
args
...
);
}
template
<
typename
Container
,
typename
Fun
>
static
inline
bool
eval
_or
(
Container
const
&
c
,
Fun
&
f
)
template
<
typename
Container
,
typename
Fun
,
typename
...
Args
>
static
inline
bool
eval
(
Container
const
&
c
,
Fun
&
f
,
Args
const
&
...
args
)
{
return
f
(
get
<
Begin
>
(
c
))
||
static_foreach_impl
<
Begin
+
1
,
End
,
(
Begin
+
1
>
End
)
>::
eval_or
(
c
,
f
);
return
f
(
get
<
Begin
>
(
c
),
args
...)
&&
static_foreach_impl
<
(
Begin
+
1
<
End
),
Begin
+
1
,
End
>::
eval
(
c
,
f
,
args
...);
}
template
<
typename
Container
,
typename
Fun
,
typename
...
Args
>
static
inline
bool
eval_or
(
Container
const
&
c
,
Fun
&
f
,
Args
const
&
...
args
)
{
return
f
(
get
<
Begin
>
(
c
),
args
...)
||
static_foreach_impl
<
(
Begin
+
1
<
End
),
Begin
+
1
,
End
>::
eval_or
(
c
,
f
,
args
...);
}
};
template
<
size_t
X
>
struct
static_foreach_impl
<
X
,
X
,
false
>
{
template
<
typename
Container
,
typename
Fun
>
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
>
struct
static_foreach_impl
<
X
,
Y
,
true
>
struct
static_foreach_impl
<
false
,
X
,
Y
>
{
template
<
typename
Container
,
typename
Fun
>
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
<
typename
...
Args
>
static
inline
void
_
(
Args
const
&
...)
{
}
template
<
typename
...
Args
>
static
inline
void
_ref
(
Args
const
&
...)
{
}
template
<
typename
...
Args
>
static
inline
bool
eval
(
Args
const
&
...)
{
return
true
;
}
template
<
typename
...
Args
>
static
inline
bool
eval_or
(
Args
const
&
...)
{
return
false
;
}
};
/**
...
...
@@ -85,7 +82,7 @@ struct static_foreach_impl<X, Y, true>
* @brief A for loop that can be used with tuples.
*/
template
<
size_t
Begin
,
size_t
End
>
struct
static_foreach
:
static_foreach_impl
<
Begin
,
End
,
(
Begin
>
End
)
>
struct
static_foreach
:
static_foreach_impl
<
(
Begin
<
End
),
Begin
,
End
>
{
};
...
...
cppa/util/type_list.hpp
View file @
30bdfb6a
...
...
@@ -32,7 +32,9 @@
#define LIBCPPA_UTIL_TYPE_LIST_HPP
#include <typeinfo>
#include <type_traits>
#include "cppa/util/tbind.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/type_pair.hpp"
#include "cppa/util/void_type.hpp"
...
...
@@ -87,6 +89,18 @@ struct type_list<Head, Tail...>
};
template
<
typename
T
>
struct
is_type_list
{
static
constexpr
bool
value
=
false
;
};
template
<
typename
...
Ts
>
struct
is_type_list
<
type_list
<
Ts
...
>
>
{
static
constexpr
bool
value
=
true
;
};
// static list list::zip(list, list)
template
<
class
ListA
,
class
ListB
>
...
...
@@ -109,6 +123,37 @@ struct tl_zip<type_list<LhsElements...>, type_list<RhsElements...> >
"Lists have different size"
);
};
// static list list::zip_with_index(list)
template
<
bool
Done
,
class
List
,
size_t
Pos
,
size_t
...>
struct
tl_zip_with_index_impl
;
template
<
class
List
,
size_t
Pos
,
size_t
...
Range
>
struct
tl_zip_with_index_impl
<
false
,
List
,
Pos
,
Range
...
>
:
tl_zip_with_index_impl
<
List
::
size
==
(
Pos
+
1
),
List
,
(
Pos
+
1
),
Range
...,
Pos
>
{
};
template
<
typename
...
Ts
,
size_t
Pos
,
size_t
...
Range
>
struct
tl_zip_with_index_impl
<
true
,
type_list
<
Ts
...
>
,
Pos
,
Range
...
>
{
typedef
type_list
<
type_pair
<
std
::
integral_constant
<
size_t
,
Range
>
,
Ts
>
...
>
type
;
};
template
<
class
List
>
struct
tl_zip_with_index
{
typedef
typename
tl_zip_with_index_impl
<
false
,
List
,
0
>::
type
type
;
};
template
<
>
struct
tl_zip_with_index
<
type_list
<>
>
{
typedef
type_list
<>
type
;
};
// list list::reverse()
template
<
class
From
,
typename
...
Elements
>
...
...
@@ -141,39 +186,47 @@ struct tl_reverse
* @brief Finds the first element of type @p What beginning at
* index @p Pos.
*/
template
<
class
List
,
t
ypename
What
,
int
Pos
=
0
>
template
<
class
List
,
t
emplate
<
typename
>
class
Predicate
,
int
Pos
=
0
>
struct
tl_find_impl
;
template
<
t
ypename
What
,
int
Pos
>
struct
tl_find_impl
<
type_list
<>
,
What
,
Pos
>
template
<
t
emplate
<
typename
>
class
Predicate
,
int
Pos
>
struct
tl_find_impl
<
type_list
<>
,
Predicate
,
Pos
>
{
static
constexpr
int
value
=
-
1
;
typedef
type_list
<>
rest_list
;
};
template
<
typename
What
,
int
Pos
,
typename
...
Tail
>
struct
tl_find_impl
<
type_list
<
What
,
Tail
...
>
,
What
,
Pos
>
template
<
template
<
typename
>
class
Predicate
,
int
Pos
,
typename
Head
,
typename
...
Tail
>
struct
tl_find_impl
<
type_list
<
Head
,
Tail
...
>
,
Predicate
,
Pos
>
{
static
constexpr
int
value
=
Pos
;
typedef
type_list
<
Tail
...
>
rest_list
;
static
constexpr
int
value
=
Predicate
<
Head
>::
value
?
Pos
:
tl_find_impl
<
type_list
<
Tail
...
>
,
Predicate
,
Pos
+
1
>::
value
;
};
template
<
typename
What
,
int
Pos
,
typename
Head
,
typename
...
Tail
>
struct
tl_find_impl
<
type_list
<
Head
,
Tail
...
>
,
What
,
Pos
>
/**
* @brief Finds the first element of type @p What beginning at
* index @p Pos.
*/
template
<
class
List
,
typename
What
,
int
Pos
=
0
>
struct
tl_find
{
static
constexpr
int
value
=
tl_find_impl
<
type_list
<
Tail
...
>
,
What
,
Pos
+
1
>::
value
;
typedef
typename
tl_find_impl
<
type_list
<
Tail
...
>
,
What
,
Pos
+
1
>::
rest_list
rest_list
;
static
constexpr
int
value
=
tl_find_impl
<
List
,
tbind
<
std
::
is_same
,
What
>::
template
type
,
Pos
>
::
value
;
};
/**
* @brief Finds the first element
of type @p What
beginning at
* @brief Finds the first element
satisfying @p Predicate
beginning at
* index @p Pos.
*/
template
<
class
List
,
class
What
,
int
Pos
=
0
>
struct
tl_find
template
<
class
List
,
template
<
typename
>
class
Predicate
,
int
Pos
=
0
>
struct
tl_find
_if
{
static
constexpr
int
value
=
tl_find_impl
<
List
,
What
,
Pos
>::
value
;
typedef
typename
tl_find_impl
<
List
,
What
,
Pos
>::
rest_list
rest_list
;
static
constexpr
int
value
=
tl_find_impl
<
List
,
Predicate
,
Pos
>::
value
;
};
// list list::first_n(size_t)
...
...
@@ -453,18 +506,192 @@ struct tl_filter<type_list<T...>, Predicate>
};
/**
* @brief Create a new list containing all elements which
* @brief Create
s
a new list containing all elements which
* do not satisfy @p Predicate.
*/
template
<
class
List
,
template
<
typename
>
class
Predicate
>
struct
tl_filter_not
;
template
<
template
<
typename
>
class
Predicate
>
struct
tl_filter_not
<
type_list
<>
,
Predicate
>
{
typedef
type_list
<>
type
;
};
template
<
template
<
typename
>
class
Predicate
,
typename
...
T
>
struct
tl_filter_not
<
type_list
<
T
...
>
,
Predicate
>
{
typedef
typename
tl_filter_impl
<
type_list
<
T
...
>
,
!
Predicate
<
T
>::
value
...
>::
type
type
;
};
/**
* @brief Creates a new list containing all elements which
* are not equal to @p Type.
*/
template
<
class
List
,
class
Type
>
struct
tl_filter_type
;
template
<
class
Type
,
typename
...
T
>
struct
tl_filter_type
<
type_list
<
T
...
>
,
Type
>
{
typedef
typename
tl_filter_impl
<
type_list
<
T
...
>
,
std
::
is_same
<
T
,
Type
>::
value
...
>::
type
type
;
};
// list list::distinct(list)
/**
* @brief Creates a new list from @p List without any duplicate elements.
*/
template
<
class
List
>
struct
tl_distinct
;
template
<
>
struct
tl_distinct
<
type_list
<>
>
{
typedef
type_list
<>
type
;
};
template
<
typename
Head
,
typename
...
Tail
>
struct
tl_distinct
<
type_list
<
Head
,
Tail
...
>
>
{
typedef
typename
tl_concat
<
type_list
<
Head
>
,
typename
tl_distinct
<
typename
tl_filter_type
<
type_list
<
Tail
...
>
,
Head
>::
type
>::
type
>::
type
type
;
};
// list list::resize(list, size, fill_type)
template
<
class
List
,
bool
OldSizeLessNewSize
,
size_t
OldSize
,
size_t
NewSize
,
typename
FillType
>
struct
tl_resize_impl
;
template
<
class
List
,
size_t
OldSize
,
size_t
NewSize
,
typename
FillType
>
struct
tl_resize_impl
<
List
,
false
,
OldSize
,
NewSize
,
FillType
>
{
typedef
typename
tl_first_n
<
List
,
NewSize
>::
type
type
;
};
template
<
class
List
,
size_t
Size
,
typename
FillType
>
struct
tl_resize_impl
<
List
,
false
,
Size
,
Size
,
FillType
>
{
typedef
List
type
;
};
template
<
class
List
,
size_t
OldSize
,
size_t
NewSize
,
typename
FillType
>
struct
tl_resize_impl
<
List
,
true
,
OldSize
,
NewSize
,
FillType
>
{
typedef
typename
tl_resize_impl
<
typename
tl_push_back
<
List
,
FillType
>::
type
,
(
OldSize
+
1
)
<
NewSize
,
OldSize
+
1
,
NewSize
,
FillType
>::
type
type
;
};
/**
* @brief Resizes the list to contain @p NewSize elements and uses
* @p FillType to initialize the new elements with.
*/
template
<
class
List
,
size_t
NewSize
,
typename
FillType
>
struct
tl_resize
{
typedef
typename
tl_resize_impl
<
List
,
(
List
::
size
<
NewSize
),
List
::
size
,
NewSize
,
FillType
>::
type
type
;
};
template
<
class
List
>
struct
tl_is_zipped
{
static
constexpr
bool
value
=
tl_forall
<
List
,
is_type_pair
>::
value
;
};
/**
* @brief Removes trailing @p What elements from the end.
*/
template
<
class
List
,
typename
What
>
struct
tl_trim
{
typedef
typename
util
::
if_else
<
std
::
is_same
<
typename
List
::
back
,
What
>
,
typename
tl_trim
<
typename
tl_pop_back
<
List
>::
type
,
What
>::
type
,
util
::
wrapped
<
List
>
>::
type
type
;
};
template
<
typename
What
>
struct
tl_trim
<
type_list
<>
,
What
>
{
typedef
type_list
<>
type
;
};
// list list::group_by(list, predicate)
template
<
bool
Append
,
typename
What
,
class
Where
>
struct
tl_group_by_impl_step
;
template
<
typename
What
,
typename
...
Ts
>
struct
tl_group_by_impl_step
<
true
,
What
,
type_list
<
Ts
...
>
>
{
typedef
type_list
<
type_list
<
Ts
...,
What
>
>
type
;
};
template
<
typename
What
,
class
List
>
struct
tl_group_by_impl_step
<
false
,
What
,
List
>
{
typedef
type_list
<
List
,
type_list
<
What
>
>
type
;
};
template
<
class
In
,
class
Out
,
template
<
typename
,
typename
>
class
Predicate
>
struct
tl_group_by_impl
{
typedef
typename
Out
::
back
last_group
;
typedef
typename
tl_group_by_impl_step
<
Predicate
<
typename
In
::
head
,
typename
last_group
::
back
>::
value
,
typename
In
::
head
,
last_group
>::
type
suffix
;
typedef
typename
tl_pop_back
<
Out
>::
type
prefix
;
typedef
typename
tl_concat
<
prefix
,
suffix
>::
type
new_out
;
typedef
typename
tl_group_by_impl
<
typename
In
::
tail
,
new_out
,
Predicate
>::
type
type
;
};
template
<
template
<
typename
,
typename
>
class
Predicate
,
typename
Head
,
typename
...
Tail
>
struct
tl_group_by_impl
<
type_list
<
Head
,
Tail
...
>
,
type_list
<>
,
Predicate
>
{
typedef
typename
tl_group_by_impl
<
type_list
<
Tail
...
>
,
type_list
<
type_list
<
Head
>
>
,
Predicate
>::
type
type
;
};
template
<
class
Out
,
template
<
typename
,
typename
>
class
Predicate
>
struct
tl_group_by_impl
<
type_list
<>
,
Out
,
Predicate
>
{
typedef
Out
type
;
};
template
<
class
List
,
template
<
typename
,
typename
>
class
Predicate
>
struct
tl_group_by
{
typedef
typename
tl_group_by_impl
<
List
,
type_list
<>
,
Predicate
>::
type
type
;
};
/**
* @}
*/
...
...
cppa/util/type_pair.hpp
View file @
30bdfb6a
...
...
@@ -44,6 +44,18 @@ struct type_pair
typedef
Second
second
;
};
template
<
class
What
>
struct
is_type_pair
{
static
constexpr
bool
value
=
false
;
};
template
<
typename
First
,
typename
Second
>
struct
is_type_pair
<
type_pair
<
First
,
Second
>
>
{
static
constexpr
bool
value
=
true
;
};
}
}
// namespace cppa::util
#endif // TYPE_PAIR_HPP
cppa/util/void_type.hpp
View file @
30bdfb6a
...
...
@@ -40,6 +40,14 @@ struct void_type
{
typedef
void_type
head
;
typedef
type_list
<>
tail
;
constexpr
void_type
()
{
}
constexpr
void_type
(
void_type
const
&
)
{
}
void_type
&
operator
=
(
void_type
const
&
)
=
default
;
// anything could be used to initialize a void...
template
<
typename
Arg0
,
typename
...
Args
>
void_type
(
Arg0
&&
,
Args
&&
...)
{
}
};
inline
bool
operator
==
(
void_type
const
&
,
void_type
const
&
)
{
return
true
;
}
...
...
src/abstract_tuple.cpp
View file @
30bdfb6a
...
...
@@ -50,4 +50,9 @@ std::type_info const* abstract_tuple::type_token() const
return
&
typeid
(
void
);
}
void
const
*
abstract_tuple
::
native_data
()
const
{
return
nullptr
;
}
}
}
// namespace cppa::detail
unit_testing/test__tuple.cpp
View file @
30bdfb6a
...
...
@@ -18,6 +18,10 @@
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/invokable.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/object_array.hpp"
#include <cxxabi.h>
using
std
::
cout
;
using
std
::
endl
;
...
...
@@ -28,6 +32,15 @@ template<class Expr, class Guard, typename Result, typename... Args>
class
tpartial_function
{
bool
collect
(
detail
::
tdata
<>&
)
{
return
true
;
}
template
<
typename
TData
,
typename
T0
,
typename
...
Ts
>
bool
collect
(
TData
&
td
,
T0
const
&
arg0
,
Ts
const
&
...
args
)
{
td
.
head
=
arg0
;
return
collect
(
td
.
tail
(),
args
...);
}
public:
tpartial_function
(
Guard
&&
g
,
Expr
&&
e
)
...
...
@@ -35,7 +48,12 @@ class tpartial_function
{
}
tpartial_function
(
tpartial_function
&&
)
=
default
;
tpartial_function
(
tpartial_function
&&
other
)
:
m_guard
(
std
::
move
(
other
.
m_guard
))
,
m_expr
(
std
::
move
(
other
.
m_expr
))
{
}
tpartial_function
(
tpartial_function
const
&
)
=
default
;
bool
defined_at
(
Args
const
&
...
args
)
...
...
@@ -45,44 +63,797 @@ class tpartial_function
Result
operator
()(
Args
const
&
...
args
)
{
return
m_expr
(
args
...);
if
(
collect
(
m_args
,
args
...))
return
m_expr
(
args
...);
throw
std
::
logic_error
(
"oops"
);
}
private:
typedef
util
::
type_list
<
ge_reference_wrapper
<
Args
>
...
>
TransformedArgs
;
typename
detail
::
tdata_from_type_list
<
TransformedArgs
>::
type
m_args
;
Guard
m_guard
;
Expr
m_expr
;
};
template
<
typename
T
>
T
const
&
fw
(
T
const
&
value
)
{
return
value
;
}
template
<
typename
T
>
struct
rm_option
{
typedef
T
type
;
};
template
<
typename
T
>
struct
rm_option
<
option
<
T
>
>
{
typedef
T
type
;
};
template
<
typename
ArgType
,
typename
Transformer
>
struct
cf_transformed_type
{
typedef
typename
util
::
get_callable_trait
<
Transformer
>::
result_type
result
;
typedef
typename
rm_option
<
result
>::
type
type
;
};
template
<
typename
ArgType
>
struct
cf_transformed_type
<
ArgType
,
util
::
void_type
>
{
typedef
ge_reference_wrapper
<
ArgType
>
type
;
};
struct
invoke_policy_helper
{
size_t
i
;
detail
::
abstract_tuple
const
&
tup
;
invoke_policy_helper
(
detail
::
abstract_tuple
const
&
tp
)
:
i
(
0
),
tup
(
tp
)
{
}
template
<
typename
T
>
void
operator
()(
ge_reference_wrapper
<
T
>&
storage
)
{
storage
=
*
reinterpret_cast
<
T
const
*>
(
tup
.
at
(
i
++
));
}
};
template
<
wildcard_position
,
class
ArgsList
>
struct
invoke_policy
;
template
<
typename
...
Args
>
struct
invoke_policy
<
wildcard_position
::
nil
,
util
::
type_list
<
Args
...
>
>
{
template
<
typename
Target
>
static
bool
invoke_args
(
Target
&
target
,
Args
const
&
...
args
)
{
return
target
(
args
...);
}
template
<
typename
Target
,
typename
...
WrongArgs
>
static
bool
invoke_args
(
Target
&
,
WrongArgs
const
&
...)
{
return
false
;
}
template
<
typename
Target
>
static
bool
invoke
(
Target
&
target
,
std
::
type_info
const
&
arg_types
,
detail
::
tuple_impl_info
timpl
,
void
const
*
native_arg
,
detail
::
abstract_tuple
const
&
tup
)
{
if
(
arg_types
==
typeid
(
util
::
type_list
<
Args
...
>
))
{
if
(
native_arg
)
{
auto
arg
=
reinterpret_cast
<
detail
::
tdata
<
Args
...
>
const
*>
(
native_arg
);
return
util
::
unchecked_apply_tuple
<
bool
>
(
target
,
*
arg
);
}
// 'fall through'
}
else
if
(
timpl
==
detail
::
dynamically_typed
)
{
auto
&
arr
=
detail
::
static_types_array
<
Args
...
>::
arr
;
if
(
tup
.
size
()
!=
sizeof
...(
Args
))
{
return
false
;
}
for
(
size_t
i
=
0
;
i
<
sizeof
...(
Args
);
++
i
)
{
if
(
arr
[
i
]
!=
tup
.
type_at
(
i
))
{
return
false
;
}
}
// 'fall through'
}
else
{
return
false
;
}
// either dynamically typed or statically typed but not a native tuple
detail
::
tdata
<
ge_reference_wrapper
<
Args
>
...
>
ttup
;
invoke_policy_helper
iph
{
tup
};
util
::
static_foreach
<
0
,
sizeof
...(
Args
)
>::
_ref
(
ttup
,
iph
);
return
util
::
apply_tuple
(
target
,
ttup
);
}
};
template
<
class
Transformers
,
class
Args
>
class
apply_policy
{
public:
template
<
typename
...
Ts
>
apply_policy
(
Ts
&&
...
args
)
:
m_transformer
(
std
::
forward
<
Ts
>
(
args
)...)
{
}
apply_policy
(
apply_policy
&&
)
=
default
;
apply_policy
(
apply_policy
const
&
)
=
default
;
template
<
class
Guard
,
class
Expr
,
typename
...
Ts
>
bool
operator
()(
Guard
&
guard
,
Expr
&
expr
,
Ts
const
&
...
args
)
const
{
typename
detail
::
tdata_from_type_list
<
typename
util
::
tl_zipped_apply
<
typename
util
::
tl_zip
<
Args
,
typename
util
::
tl_resize
<
Transformers
,
Args
::
size
,
util
::
void_type
>::
type
>::
type
,
cf_transformed_type
>::
type
>::
type
m_args
;
if
(
collect
(
m_args
,
m_transformer
,
args
...))
{
if
(
util
::
unchecked_apply_tuple
<
bool
>
(
guard
,
m_args
))
{
util
::
apply_tuple
(
expr
,
m_args
);
return
true
;
}
}
return
false
;
}
private:
template
<
class
Storage
,
typename
T
>
static
inline
bool
fetch_
(
Storage
&
storage
,
T
const
&
value
)
{
storage
=
value
;
return
true
;
}
template
<
class
Result
>
static
inline
bool
fetch_
(
Result
&
storage
,
option
<
Result
>&&
value
)
{
if
(
value
)
{
storage
=
std
::
move
(
*
value
);
return
true
;
}
return
false
;
}
template
<
class
Storage
,
typename
Fun
,
typename
T
>
static
inline
bool
fetch
(
Storage
&
storage
,
Fun
const
&
fun
,
T
const
&
arg
)
{
return
fetch_
(
storage
,
fun
(
arg
));
}
template
<
typename
T
>
static
inline
bool
fetch
(
ge_reference_wrapper
<
T
>&
storage
,
util
::
void_type
const
&
,
T
const
&
arg
)
{
storage
=
arg
;
return
true
;
}
static
inline
bool
collect
(
detail
::
tdata
<>&
,
detail
::
tdata
<>
const
&
)
{
return
true
;
}
template
<
class
TData
,
typename
T0
,
typename
...
Ts
>
static
inline
bool
collect
(
TData
&
td
,
detail
::
tdata
<>
const
&
,
T0
const
&
arg0
,
Ts
const
&
...
args
)
{
td
.
set
(
arg0
,
args
...);
return
true
;
}
template
<
class
TData
,
class
Trans
,
typename
T0
,
typename
...
Ts
>
static
inline
bool
collect
(
TData
&
td
,
Trans
const
&
tr
,
T0
const
&
arg0
,
Ts
const
&
...
args
)
{
return
fetch
(
td
.
head
,
tr
.
head
,
arg0
)
&&
collect
(
td
.
tail
(),
tr
.
tail
(),
args
...);
}
typename
detail
::
tdata_from_type_list
<
Transformers
>::
type
m_transformer
;
};
template
<
typename
Expr
,
size_t
ExprArgs
,
size_t
NumArgs
>
struct
apply_args
{
template
<
typename
Arg0
,
typename
...
Args
>
static
inline
void
_
(
Expr
&
expr
,
Arg0
const
&
,
Args
const
&
...
args
)
{
apply_args
<
Expr
,
ExprArgs
,
NumArgs
-
1
>::
_
(
expr
,
args
...);
}
};
template
<
typename
Expr
,
size_t
Num
>
struct
apply_args
<
Expr
,
Num
,
Num
>
{
template
<
typename
...
Args
>
static
inline
void
_
(
Expr
&
expr
,
Args
const
&
...
args
)
{
expr
(
args
...);
}
};
template
<
class
Args
>
class
apply_policy
<
util
::
type_list
<>
,
Args
>
{
public:
apply_policy
(
detail
::
tdata
<>
const
&
)
{
}
apply_policy
()
=
default
;
apply_policy
(
apply_policy
const
&
)
=
default
;
template
<
class
Guard
,
class
Expr
,
typename
...
Ts
>
bool
operator
()(
Guard
&
guard
,
Expr
&
expr
,
Ts
const
&
...
args
)
const
{
if
(
guard
(
args
...))
{
typedef
typename
util
::
get_callable_trait
<
Expr
>::
type
ctrait
;
apply_args
<
Expr
,
ctrait
::
arg_types
::
size
,
sizeof
...(
Ts
)
>::
_
(
expr
,
args
...);
return
true
;
}
return
false
;
}
};
template
<
class
InvokePolicy
>
struct
invoke_helper_
{
template
<
class
Leaf
>
bool
operator
()(
Leaf
const
&
leaf
,
std
::
type_info
const
&
v0
,
detail
::
tuple_impl_info
v1
,
void
const
*
v2
,
detail
::
abstract_tuple
const
&
v3
)
const
{
return
InvokePolicy
::
invoke
(
leaf
,
v0
,
v1
,
v2
,
v3
);
}
template
<
class
Leaf
,
typename
...
Args
>
bool
operator
()(
Leaf
const
&
leaf
,
Args
const
&
...
args
)
const
{
return
InvokePolicy
::
invoke_args
(
leaf
,
args
...);
}
};
struct
invoke_helper
{
template
<
class
ArgTypes
,
class
...
Leaves
,
typename
...
Args
>
bool
operator
()(
detail
::
tdata
<
ArgTypes
,
Leaves
...
>
const
&
list
,
Args
const
&
...
args
)
const
{
typedef
invoke_policy
<
get_wildcard_position
<
ArgTypes
>
(),
ArgTypes
>
ipolicy
;
invoke_helper_
<
ipolicy
>
fun
;
return
util
::
static_foreach
<
1
,
sizeof
...(
Leaves
)
+
1
>::
eval_or
(
list
,
fun
,
args
...);
}
};
template
<
class
Expr
,
class
Guard
,
class
Transformers
,
class
ArgTypes
>
class
conditional_fun_leaf
;
template
<
class
Expr
,
class
Guard
,
class
Transformers
,
typename
...
Args
>
class
conditional_fun_leaf
<
Expr
,
Guard
,
Transformers
,
util
::
type_list
<
Args
...
>
>
{
public:
typedef
util
::
type_list
<
Args
...
>
args_list
;
template
<
typename
G
,
typename
E
,
typename
...
TFuns
>
conditional_fun_leaf
(
G
&&
g
,
E
&&
e
,
TFuns
&&
...
tfuns
)
:
m_apply
(
std
::
forward
<
TFuns
>
(
tfuns
)...)
,
m_guard
(
std
::
forward
<
G
>
(
g
)),
m_expr
(
std
::
forward
<
E
>
(
e
))
{
}
conditional_fun_leaf
(
conditional_fun_leaf
const
&
)
=
default
;
bool
operator
()(
Args
const
&
...
args
)
const
{
return
m_apply
(
m_guard
,
m_expr
,
args
...);
}
private:
detail
::
tdata
<
Args
...
>
m_args
;
typedef
typename
util
::
tl_trim
<
Transformers
,
util
::
void_type
>::
type
trimmed
;
apply_policy
<
trimmed
,
args_list
>
m_apply
;
Guard
m_guard
;
Expr
m_expr
;
};
template
<
class
Expr
,
class
Guard
,
typename
Result
,
class
ArgTypes
>
struct
tpf_
;
template
<
class
ArgTypes
,
class
Expr
,
class
Guard
,
typename
...
TFuns
>
struct
cfl_
{
typedef
conditional_fun_leaf
<
Expr
,
Guard
,
util
::
type_list
<
TFuns
...
>
,
ArgTypes
>
type
;
};
template
<
class
ArgTypes
,
class
LeavesTData
,
class
...
LeafImpl
>
struct
cfh_
{
typedef
LeavesTData
leaves_type
;
// tdata<tdata...>
typedef
typename
leaves_type
::
back_type
back_leaf
;
// tdata
// manipulate leaves type to push back leaf_impl
typedef
typename
util
::
tl_pop_back
<
typename
leaves_type
::
types
>::
type
prefix
;
// type_list<tdata...>
typedef
typename
detail
::
tdata_from_type_list
<
typename
util
::
tl_concat
<
typename
back_leaf
::
types
,
util
::
type_list
<
LeafImpl
...
>
>::
type
>::
type
suffix
;
// tdata
typedef
typename
util
::
tl_push_back
<
prefix
,
suffix
>::
type
concatenated
;
// type_list<tdata...>
typedef
typename
detail
::
tdata_from_type_list
<
concatenated
>::
type
type
;
};
namespace
cppa
{
namespace
detail
{
template
<
class
Lhs
,
class
Rhs
>
struct
tdata_concatenate
;
template
<
class
...
Lhs
,
class
...
Rhs
>
struct
tdata_concatenate
<
tdata
<
Lhs
...
>
,
tdata
<
Rhs
...
>
>
{
typedef
tdata
<
Lhs
...,
Rhs
...
>
type
;
};
}
}
// namespace cppa::detail
template
<
class
Leaves
>
class
conditional_fun
{
public:
template
<
typename
...
Args
>
conditional_fun
(
Args
&&
...
args
)
:
m_leaves
(
std
::
forward
<
Args
>
(
args
)...)
{
}
conditional_fun
(
conditional_fun
&&
other
)
:
m_leaves
(
std
::
move
(
other
.
m_leaves
))
{
}
conditional_fun
(
conditional_fun
const
&
)
=
default
;
//conditional_fun& operator=(conditional_fun&&) = default;
//conditional_fun& operator=(conditional_fun const&) = default;
typedef
void
const
*
const_void_ptr
;
bool
invoke
(
std
::
type_info
const
&
arg_types
,
detail
::
tuple_impl_info
timpl
,
const_void_ptr
native_arg
,
detail
::
abstract_tuple
const
&
tup
)
const
{
invoke_helper
fun
;
return
util
::
static_foreach
<
0
,
Leaves
::
tdata_size
>::
eval_or
(
m_leaves
,
fun
,
arg_types
,
timpl
,
native_arg
,
tup
);
}
bool
invoke
(
any_tuple
const
&
tup
)
const
{
auto
const
&
cvals
=
*
(
tup
.
cvals
());
return
invoke
(
*
(
cvals
.
type_token
()),
cvals
.
impl_type
(),
cvals
.
native_data
(),
cvals
);
}
template
<
typename
...
Args
>
bool
operator
()(
Args
const
&
...
args
)
{
invoke_helper
fun
;
return
util
::
static_foreach
<
0
,
Leaves
::
tdata_size
>::
eval_or
(
m_leaves
,
fun
,
args
...);
}
typedef
typename
Leaves
::
back_type
back_leaf
;
typedef
typename
back_leaf
::
head_type
back_arg_types
;
template
<
typename
OtherLeaves
>
conditional_fun
<
typename
detail
::
tdata_concatenate
<
Leaves
,
OtherLeaves
>::
type
>
or_else
(
conditional_fun
<
OtherLeaves
>
const
&
other
)
const
{
return
{
m_leaves
,
other
.
m_leaves
};
}
template
<
class
...
LeafImpl
>
conditional_fun
<
typename
cfh_
<
back_arg_types
,
Leaves
,
LeafImpl
...
>::
type
>
or_else
(
conditional_fun
<
detail
::
tdata
<
detail
::
tdata
<
back_arg_types
,
LeafImpl
...
>>>
const
&
other
)
const
{
return
{
m_leaves
,
other
.
m_leaves
.
back
().
tail
()};
}
template
<
class
...
LeafImpl
,
class
Others0
,
class
...
Others
>
conditional_fun
<
typename
detail
::
tdata_concatenate
<
typename
cfh_
<
back_arg_types
,
Leaves
,
LeafImpl
...
>::
type
,
detail
::
tdata
<
Others0
,
Others
...
>
>::
type
>
or_else
(
conditional_fun
<
detail
::
tdata
<
detail
::
tdata
<
back_arg_types
,
LeafImpl
...
>
,
Others0
,
Others
...
>>
const
&
other
)
const
{
typedef
conditional_fun
<
detail
::
tdata
<
detail
::
tdata
<
back_arg_types
,
LeafImpl
...
>>>
head_fun
;
typedef
conditional_fun
<
detail
::
tdata
<
Others0
,
Others
...
>>
tail_fun
;
return
or_else
(
head_fun
{
other
.
m_leaves
.
head
})
.
or_else
(
tail_fun
{
other
.
m_leaves
.
tail
()});
}
//private:
// structure: tdata< tdata<type_list<...>, ...>,
// tdata<type_list<...>, ...>,
// ...>
Leaves
m_leaves
;
};
template
<
class
ArgTypes
,
class
Expr
,
class
Guard
,
typename
...
TFuns
>
conditional_fun
<
detail
::
tdata
<
detail
::
tdata
<
ArgTypes
,
typename
cfl_
<
ArgTypes
,
Expr
,
Guard
,
TFuns
...
>::
type
>>>
cfun
(
Expr
e
,
Guard
g
,
TFuns
...
tfs
)
{
typedef
detail
::
tdata
<
ArgTypes
,
typename
cfl_
<
ArgTypes
,
Expr
,
Guard
,
TFuns
...
>::
type
>
result
;
typedef
typename
result
::
tail_type
ttype
;
typedef
typename
ttype
::
head_type
leaf_type
;
typedef
typename
util
::
get_callable_trait
<
Expr
>::
arg_types
expr_args
;
static_assert
(
ArgTypes
::
size
>=
expr_args
::
size
,
"Functor has too many arguments"
);
return
result
{
ArgTypes
{},
leaf_type
{
std
::
move
(
g
),
std
::
move
(
e
),
std
::
move
(
tfs
)...}
};
}
#define VERBOSE(LineOfCode) cout << #LineOfCode << " = " << (LineOfCode) << endl
float
tofloat
(
int
i
)
{
return
i
;
}
struct
dummy_guard
{
template
<
typename
...
Args
>
inline
bool
operator
()(
Args
const
&
...)
const
{
return
true
;
}
};
template
<
typename
...
Args
>
any_tuple
make_any_tuple
(
Args
&&
...
args
)
{
return
make_cow_tuple
(
std
::
forward
<
Args
>
(
args
)...);
}
struct
from_args
{
};
template
<
class
Guard
,
class
Transformers
,
class
Pattern
>
struct
cf_builder
{
Guard
m_guard
;
typename
detail
::
tdata_from_type_list
<
Transformers
>::
type
m_funs
;
public:
template
<
typename
...
Args
>
cf_builder
(
from_args
const
&
,
Args
const
&
...
args
)
:
m_guard
(
args
...),
m_funs
(
args
...)
{
}
template
<
typename
G
>
cf_builder
(
G
&&
g
)
:
m_guard
(
std
::
forward
<
G
>
(
g
))
{
}
template
<
typename
G
,
typename
F
>
cf_builder
(
G
&&
g
,
F
&&
f
)
:
m_guard
(
std
::
forward
<
G
>
(
g
)),
m_funs
(
std
::
forward
<
F
>
(
f
))
{
}
template
<
typename
NewGuard
>
cf_builder
<
NewGuard
,
Transformers
,
Pattern
>
when
(
NewGuard
ng
)
{
return
{
ng
,
m_funs
};
}
template
<
typename
Expr
>
conditional_fun
<
detail
::
tdata
<
detail
::
tdata
<
Pattern
,
conditional_fun_leaf
<
Expr
,
Guard
,
Transformers
,
Pattern
>>>>
operator
>>
(
Expr
expr
)
const
{
typedef
conditional_fun_leaf
<
Expr
,
Guard
,
Transformers
,
Pattern
>
tfun
;
typedef
detail
::
tdata
<
Pattern
,
tfun
>
result
;
return
result
{
Pattern
{},
tfun
{
m_guard
,
std
::
move
(
expr
),
m_funs
}};
}
};
template
<
typename
...
T
>
cf_builder
<
dummy_guard
,
util
::
type_list
<>
,
util
::
type_list
<
T
...
>
>
_on
()
{
return
{
dummy_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
<
class
Expr
,
class
Guard
,
typename
Result
,
typename
...
Ts
>
struct
t
pf_
<
Expr
,
Guard
,
Result
,
util
::
type_list
<
Ts
...
>
>
template
<
typename
T
>
struct
t
o_void_impl
<
false
,
T
>
{
typedef
t
partial_function
<
Expr
,
Guard
,
Result
,
Ts
...
>
type
;
typedef
t
ypename
add_ptr_to_fun
<
T
>::
type
type
;
};
template
<
class
Expr
,
class
Guard
>
template
<
typename
T
>
struct
not_callable_to_void
:
to_void_impl
<
detail
::
is_boxed
<
T
>::
value
||
!
util
::
is_callable
<
T
>::
value
,
T
>
{
};
typename
tpf_
<
Expr
,
Guard
,
typename
util
::
get_callable_trait
<
Expr
>::
result_type
,
typename
util
::
get_callable_trait
<
Expr
>::
arg_types
>::
type
tfun
(
Expr
e
,
Guard
g
)
template
<
typename
T
>
struct
boxed_and_callable_to_void
:
to_void_impl
<
detail
::
is_boxed
<
T
>::
value
||
util
::
is_callable
<
T
>::
value
,
T
>
{
return
{
std
::
move
(
g
),
std
::
move
(
e
)};
};
template
<
typename
Pattern
>
class
value_guard
;
template
<
typename
...
Types
>
class
value_guard
<
util
::
type_list
<
Types
...
>
>
{
detail
::
tdata
<
Types
...
>
m_args
;
inline
bool
_eval
(
util
::
void_type
const
&
,
detail
::
tdata
<>
const
&
)
const
{
return
true
;
}
template
<
class
Tail
,
typename
Arg0
,
typename
...
Args
>
inline
bool
_eval
(
util
::
void_type
const
&
,
Tail
const
&
tail
,
Arg0
const
&
,
Args
const
&
...
args
)
const
{
return
_eval
(
tail
.
head
,
tail
.
tail
(),
args
...);
}
template
<
typename
Head
,
class
Tail
,
typename
Arg0
,
typename
...
Args
>
inline
bool
_eval
(
Head
const
&
head
,
Tail
const
&
tail
,
Arg0
const
&
arg0
,
Args
const
&
...
args
)
const
{
return
head
==
arg0
&&
_eval
(
tail
.
head
,
tail
.
tail
(),
args
...);
}
public:
template
<
typename
...
Args
>
value_guard
(
Args
const
&
...
args
)
:
m_args
(
args
...)
{
}
inline
bool
operator
()(
Types
const
&
...
args
)
const
{
return
_eval
(
m_args
.
head
,
m_args
.
tail
(),
args
...);
}
};
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
<
T
>::
type
type
;
};
template
<
typename
T
>
struct
pattern_type
:
pattern_type_
<
util
::
is_callable
<
T
>::
value
&&
!
detail
::
is_boxed
<
T
>::
value
,
T
>
{
};
template
<
typename
Arg0
,
typename
...
Args
>
cf_builder
<
value_guard
<
typename
util
::
tl_apply
<
util
::
type_list
<
Arg0
,
Args
...
>
,
boxed_and_callable_to_void
>::
type
>
,
typename
util
::
tl_apply
<
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
{
from_args
{},
arg0
,
args
...};
}
std
::
string
int2str
(
int
i
)
{
return
std
::
to_string
(
i
);
}
option
<
int
>
str2int
(
std
::
string
const
&
str
)
{
if
(
str
==
"42"
)
return
42
;
if
(
str
==
"41"
)
return
41
;
return
{};
}
typedef
util
::
type_list
<
int
,
int
,
int
,
float
,
int
,
float
,
float
>
zz0
;
typedef
util
::
type_list
<
util
::
type_list
<
int
,
int
,
int
>
,
util
::
type_list
<
float
>
,
util
::
type_list
<
int
>
,
util
::
type_list
<
float
,
float
>
>
zz8
;
typedef
util
::
type_list
<
util
::
type_list
<
util
::
type_pair
<
std
::
integral_constant
<
size_t
,
0
>
,
int
>
,
util
::
type_pair
<
std
::
integral_constant
<
size_t
,
1
>
,
int
>
,
util
::
type_pair
<
std
::
integral_constant
<
size_t
,
2
>
,
int
>
>
,
util
::
type_list
<
util
::
type_pair
<
std
::
integral_constant
<
size_t
,
3
>
,
float
>
>
,
util
::
type_list
<
util
::
type_pair
<
std
::
integral_constant
<
size_t
,
4
>
,
int
>
>
,
util
::
type_list
<
util
::
type_pair
<
std
::
integral_constant
<
size_t
,
5
>
,
float
>
,
util
::
type_pair
<
std
::
integral_constant
<
size_t
,
6
>
,
float
>
>
>
zz9
;
template
<
typename
First
,
typename
Second
>
struct
is_same_
:
std
::
is_same
<
typename
First
::
second
,
typename
Second
::
second
>
{
};
size_t
test__tuple
()
{
CPPA_TEST
(
test__tuple
);
using
namespace
cppa
::
placeholders
;
typedef
typename
util
::
tl_group_by
<
zz0
,
std
::
is_same
>::
type
zz1
;
typedef
typename
util
::
tl_zip_with_index
<
zz0
>::
type
zz2
;
static_assert
(
std
::
is_same
<
zz1
,
zz8
>::
value
,
"group_by failed"
);
typedef
typename
util
::
tl_group_by
<
zz2
,
is_same_
>::
type
zz3
;
static_assert
(
std
::
is_same
<
zz3
,
zz9
>::
value
,
"group_by failed"
);
cout
<<
detail
::
demangle
(
typeid
(
zz3
).
name
())
<<
endl
;
exit
(
0
);
typedef
util
::
type_list
<
int
,
int
>
token1
;
typedef
util
::
type_list
<
float
>
token2
;
//auto f00 = cfun<token1>([](int, int) { cout << "f0[1]!" << endl; }, _x1 > _x2)
// .or_else(cfun<token1>([](int, int) { cout << "f0[2]!" << endl; }, _x1 == 2 && _x2 == 2))
// .or_else(cfun<token2>([](float) { cout << "f0[3]!" << endl; }, dummy_guard{}));
auto
f00
=
_on
<
int
,
int
>
()
>>
[]()
{
};
auto
f01
=
_on
<
int
,
int
>
().
when
(
_x1
==
42
)
>>
[]()
{
};
auto
f02
=
_on
<
int
,
int
>
().
when
(
_x1
==
42
&&
_x2
*
2
==
_x1
)
>>
[]()
{
};
auto
f03
=
_on
(
42
,
val
<
int
>
)
>>
[](
int
)
{
};
auto
f04
=
_on
(
42
,
int2str
).
when
(
_x2
==
"42"
)
>>
[]()
{
};
auto
f05
=
_on
(
42
,
str2int
).
when
(
_x2
%
2
==
0
)
>>
[]()
{
};
VERBOSE
(
f00
(
42
,
42
));
VERBOSE
(
f01
(
42
,
42
));
VERBOSE
(
f02
(
42
,
42
));
VERBOSE
(
f02
(
42
,
21
));
VERBOSE
(
f03
(
42
,
42
));
VERBOSE
(
f04
(
42
,
42
));
VERBOSE
(
f04
(
42
,
std
::
string
(
"42"
)));
VERBOSE
(
f05
(
42
,
42
));
VERBOSE
(
f05
(
42
,
std
::
string
(
"41"
)));
VERBOSE
(
f05
(
42
,
std
::
string
(
"42"
)));
VERBOSE
(
f05
(
42
,
std
::
string
(
"hello world!"
)));
exit
(
0
);
auto
f0
=
cfun
<
token1
>
([](
int
,
int
)
{
cout
<<
"f0[0]!"
<<
endl
;
},
_x1
<
_x2
)
//.or_else(f00)
.
or_else
(
cfun
<
token1
>
([](
int
,
int
)
{
cout
<<
"f0[1]!"
<<
endl
;
},
_x1
>
_x2
))
.
or_else
(
cfun
<
token1
>
([](
int
,
int
)
{
cout
<<
"f0[2]!"
<<
endl
;
},
_x1
==
2
&&
_x2
==
2
))
.
or_else
(
cfun
<
token2
>
([](
float
)
{
cout
<<
"f0[3]!"
<<
endl
;
},
dummy_guard
{}))
.
or_else
(
cfun
<
token1
>
([](
int
,
int
)
{
cout
<<
"f0[4]"
<<
endl
;
},
dummy_guard
{}));
//VERBOSE(f0(make_cow_tuple(1, 2)));
VERBOSE
(
f0
(
3
,
3
));
VERBOSE
(
f0
.
invoke
(
make_any_tuple
(
3
,
3
)));
VERBOSE
(
f0
.
invoke
(
make_any_tuple
(
2
,
2
)));
VERBOSE
(
f0
.
invoke
(
make_any_tuple
(
3
,
2
)));
VERBOSE
(
f0
.
invoke
(
make_any_tuple
(
1.
f
)));
auto
f1
=
cfun
<
token1
>
([](
float
,
int
)
{
cout
<<
"f1!"
<<
endl
;
},
_x1
<
6
,
tofloat
);
VERBOSE
(
f1
.
invoke
(
make_any_tuple
(
5
,
6
)));
VERBOSE
(
f1
.
invoke
(
make_any_tuple
(
6
,
7
)));
auto
i2
=
make_any_tuple
(
1
,
2
);
VERBOSE
(
f0
.
invoke
(
*
i2
.
vals
()
->
type_token
(),
i2
.
vals
()
->
impl_type
(),
i2
.
vals
()
->
native_data
(),
*
(
i2
.
vals
())));
VERBOSE
(
f1
.
invoke
(
*
i2
.
vals
()
->
type_token
(),
i2
.
vals
()
->
impl_type
(),
i2
.
vals
()
->
native_data
(),
*
(
i2
.
vals
())));
any_tuple
dt1
;
{
auto
oarr
=
new
detail
::
object_array
;
oarr
->
push_back
(
object
::
from
(
1
));
oarr
->
push_back
(
object
::
from
(
2
));
dt1
=
any_tuple
{
static_cast
<
detail
::
abstract_tuple
*>
(
oarr
)};
}
VERBOSE
(
f0
.
invoke
(
*
dt1
.
cvals
()
->
type_token
(),
dt1
.
cvals
()
->
impl_type
(),
dt1
.
cvals
()
->
native_data
(),
*
dt1
.
cvals
()));
VERBOSE
(
f1
.
invoke
(
*
dt1
.
cvals
()
->
type_token
(),
dt1
.
cvals
()
->
impl_type
(),
dt1
.
cvals
()
->
native_data
(),
*
dt1
.
cvals
()));
exit
(
0
);
// check type correctness of make_cow_tuple()
auto
t0
=
make_cow_tuple
(
"1"
,
2
);
CPPA_CHECK
((
std
::
is_same
<
decltype
(
t0
),
cppa
::
cow_tuple
<
std
::
string
,
int
>>::
value
));
...
...
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