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
bcafa1b9
Commit
bcafa1b9
authored
Jan 20, 2012
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
match()
parent
9b2d839e
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
534 additions
and
198 deletions
+534
-198
Makefile.am
Makefile.am
+1
-1
cppa.files
cppa.files
+2
-1
cppa/any_tuple.hpp
cppa/any_tuple.hpp
+1
-9
cppa/any_tuple_view.hpp
cppa/any_tuple_view.hpp
+170
-0
cppa/detail/invokable.hpp
cppa/detail/invokable.hpp
+44
-14
cppa/detail/matches.hpp
cppa/detail/matches.hpp
+8
-6
cppa/detail/types_array.hpp
cppa/detail/types_array.hpp
+28
-0
cppa/invoke_rules.hpp
cppa/invoke_rules.hpp
+3
-0
cppa/match.hpp
cppa/match.hpp
+47
-21
cppa/option.hpp
cppa/option.hpp
+14
-12
cppa/pattern.hpp
cppa/pattern.hpp
+7
-12
cppa/to_string.hpp
cppa/to_string.hpp
+1
-0
cppa/tuple.hpp
cppa/tuple.hpp
+12
-1
cppa/tuple_cast.hpp
cppa/tuple_cast.hpp
+93
-19
cppa/tuple_view.hpp
cppa/tuple_view.hpp
+36
-51
src/any_tuple.cpp
src/any_tuple.cpp
+3
-3
src/invoke_rules.cpp
src/invoke_rules.cpp
+14
-5
unit_testing/test__pattern.cpp
unit_testing/test__pattern.cpp
+17
-24
unit_testing/test__tuple.cpp
unit_testing/test__tuple.cpp
+33
-19
No files found.
Makefile.am
View file @
bcafa1b9
...
...
@@ -84,6 +84,7 @@ nobase_library_include_HEADERS = \
cppa/channel.hpp
\
cppa/config.hpp
\
cppa/local_actor.hpp
\
cppa/match.hpp
\
cppa/cow_ptr.hpp
\
cppa/cppa.hpp
\
cppa/deserializer.hpp
\
...
...
@@ -145,7 +146,6 @@ nobase_library_include_HEADERS = \
cppa/from_string.hpp
\
cppa/fsm_actor.hpp
\
cppa/get.hpp
\
cppa/get_view.hpp
\
cppa/group.hpp
\
cppa/intrusive_ptr.hpp
\
cppa/invoke_rules.hpp
\
...
...
cppa.files
View file @
bcafa1b9
...
...
@@ -114,7 +114,6 @@ cppa/announce.hpp
cppa/util/shared_spinlock.hpp
src/shared_spinlock.cpp
cppa/util/shared_lock_guard.hpp
cppa/get_view.hpp
cppa/detail/object_array.hpp
src/object_array.cpp
cppa/any_tuple.hpp
...
...
@@ -251,3 +250,5 @@ cppa/detail/matches.hpp
cppa/util/is_mutable_ref.hpp
cppa/util/is_manipulator.hpp
cppa/util/apply_tuple.hpp
cppa/any_tuple_view.hpp
cppa/match.hpp
cppa/any_tuple.hpp
View file @
bcafa1b9
...
...
@@ -92,23 +92,15 @@ class any_tuple
class
const_iterator
{
any_tuple
const
&
ref
;
size_t
p
;
public:
inline
const_iterator
(
any_tuple
const
&
data
,
size_t
pos
=
0
)
:
ref
(
data
),
p
(
pos
)
{
}
:
ref
(
data
),
p
(
pos
)
{
}
inline
void
next
()
{
++
p
;
}
inline
bool
at_end
()
const
{
return
p
>=
ref
.
size
();
}
inline
size_t
position
()
const
{
return
p
;
}
inline
void
const
*
value
()
const
{
return
ref
.
at
(
p
);
}
inline
uniform_type_info
const
*
type
()
const
{
return
ref
.
type_at
(
p
);
}
};
inline
const_iterator
begin
()
const
{
return
{
*
this
};
}
...
...
cppa/any_tuple_view.hpp
0 → 100644
View file @
bcafa1b9
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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 ANY_TUPLE_VIEW_HPP
#define ANY_TUPLE_VIEW_HPP
#include <set>
#include <list>
#include <vector>
#include <utility>
#include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/is_primitive.hpp"
#include "cppa/detail/types_array.hpp"
namespace
cppa
{
class
any_tuple_view
{
typedef
std
::
vector
<
std
::
pair
<
uniform_type_info
const
*
,
void
const
*>
>
vector_type
;
vector_type
m_values
;
template
<
typename
T
>
void
from_list
(
T
const
&
list
)
{
auto
&
arr
=
detail
::
static_types_array
<
typename
T
::
value_type
>::
arr
;
for
(
auto
i
=
list
.
begin
();
i
!=
list
.
end
();
++
i
)
{
m_values
.
push_back
(
std
::
make_pair
(
arr
[
0
],
&
(
*
i
)));
}
}
public:
class
const_iterator
;
friend
class
const_iterator
;
any_tuple_view
(
any_tuple_view
&&
)
=
default
;
any_tuple_view
(
any_tuple_view
const
&
)
=
default
;
any_tuple_view
&
operator
=
(
any_tuple_view
&&
)
=
default
;
any_tuple_view
&
operator
=
(
any_tuple_view
const
&
)
=
default
;
any_tuple_view
(
any_tuple
const
&
tup
)
{
for
(
size_t
i
=
0
;
i
<
tup
.
size
();
++
i
)
{
m_values
.
push_back
(
std
::
make_pair
(
tup
.
type_at
(
i
),
tup
.
at
(
i
)));
}
}
template
<
typename
...
T
>
explicit
any_tuple_view
(
tuple
<
T
...
>
const
&
tup
)
{
for
(
size_t
i
=
0
;
i
<
tup
.
size
();
++
i
)
{
m_values
.
push_back
(
std
::
make_pair
(
tup
.
type_at
(
i
),
tup
.
at
(
i
)));
}
}
template
<
typename
...
T
>
any_tuple_view
(
tuple_view
<
T
...
>
const
&
tup
)
{
for
(
size_t
i
=
0
;
i
<
tup
.
size
();
++
i
)
{
m_values
.
push_back
(
std
::
make_pair
(
tup
.
type_at
(
i
),
tup
.
at
(
i
)));
}
}
template
<
typename
F
,
typename
S
>
any_tuple_view
(
std
::
pair
<
F
,
S
>
const
&
pair
)
{
auto
&
arr
=
detail
::
static_types_array
<
F
,
S
>::
arr
;
m_values
.
push_back
(
std
::
make_pair
(
arr
[
0
],
&
pair
.
first
));
m_values
.
push_back
(
std
::
make_pair
(
arr
[
1
],
&
pair
.
second
));
}
template
<
typename
T
>
any_tuple_view
(
std
::
set
<
T
>
const
&
vec
)
{
from_list
(
vec
);
}
template
<
typename
T
>
any_tuple_view
(
std
::
list
<
T
>
const
&
vec
)
{
from_list
(
vec
);
}
template
<
typename
T
>
any_tuple_view
(
std
::
vector
<
T
>
const
&
vec
)
{
from_list
(
vec
);
}
template
<
typename
T
>
any_tuple_view
(
T
const
&
val
,
typename
util
::
enable_if
<
util
::
is_primitive
<
T
>
>::
type
*
=
0
)
{
auto
&
arr
=
detail
::
static_types_array
<
T
>::
arr
;
m_values
.
push_back
(
std
::
make_pair
(
arr
[
0
],
&
val
));
}
inline
vector_type
const
&
vals
()
const
{
return
m_values
;
}
inline
size_t
size
()
const
{
return
m_values
.
size
();
}
inline
void
const
*
at
(
size_t
p
)
const
{
return
m_values
[
p
].
second
;
}
inline
uniform_type_info
const
*
type_at
(
size_t
p
)
const
{
return
m_values
[
p
].
first
;
}
inline
bool
empty
()
const
{
return
m_values
.
empty
();
}
template
<
typename
T
>
inline
T
const
&
get_as
(
size_t
p
)
const
{
return
*
reinterpret_cast
<
T
const
*>
(
at
(
p
));
}
class
const_iterator
{
typedef
typename
vector_type
::
const_iterator
vec_iterator
;
vec_iterator
pos
;
vec_iterator
end
;
public:
inline
const_iterator
(
any_tuple_view
const
&
view
)
:
pos
(
view
.
m_values
.
begin
()),
end
(
view
.
m_values
.
end
())
{
}
inline
void
next
()
{
++
pos
;
}
inline
bool
at_end
()
const
{
return
pos
==
end
;
}
inline
void
const
*
value
()
const
{
return
pos
->
second
;
}
inline
uniform_type_info
const
*
type
()
const
{
return
pos
->
first
;
}
};
inline
const_iterator
begin
()
const
{
return
{
*
this
};
}
};
}
// namespace cppa
#endif // ANY_TUPLE_VIEW_HPP
cppa/detail/invokable.hpp
View file @
bcafa1b9
...
...
@@ -38,6 +38,7 @@
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_cast.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/any_tuple_view.hpp"
#include "cppa/util/apply_tuple.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/callable_trait.hpp"
...
...
@@ -61,6 +62,7 @@ class invokable_base
invokable_base
()
=
default
;
virtual
~
invokable_base
();
virtual
bool
invoke
(
any_tuple
const
&
)
const
=
0
;
virtual
bool
invoke
(
any_tuple_view
const
&
)
const
=
0
;
};
...
...
@@ -104,6 +106,13 @@ class timed_invokable_impl : public timed_invokable
return
true
;
}
bool
invoke
(
any_tuple_view
const
&
)
const
{
m_target
();
return
true
;
}
};
class
invokable
:
public
invokable_base
...
...
@@ -129,6 +138,18 @@ class invokable_impl : public invokable
m_iimpl
;
std
::
unique_ptr
<
Pattern
>
m_pattern
;
template
<
typename
T
>
bool
invoke_impl
(
T
const
&
data
)
const
{
auto
tuple_option
=
tuple_cast
(
data
,
*
m_pattern
);
if
(
tuple_option
.
valid
())
{
util
::
apply_tuple
(
m_iimpl
.
m_fun
,
*
tuple_option
);
return
true
;
}
return
false
;
}
public:
template
<
typename
F
>
...
...
@@ -139,13 +160,12 @@ class invokable_impl : public invokable
bool
invoke
(
any_tuple
const
&
data
)
const
{
auto
tuple_option
=
tuple_cast
(
data
,
*
m_pattern
);
if
(
tuple_option
.
valid
())
{
util
::
apply_tuple
(
m_iimpl
.
m_fun
,
*
tuple_option
);
return
true
;
}
return
false
;
return
invoke_impl
(
data
);
}
bool
invoke
(
any_tuple_view
const
&
data
)
const
{
return
invoke_impl
(
data
);
}
intermediate
*
get_intermediate
(
any_tuple
const
&
data
)
...
...
@@ -174,6 +194,17 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
m_iimpl
;
std
::
unique_ptr
<
Pattern
>
m_pattern
;
template
<
typename
T
>
bool
invoke_impl
(
T
const
&
data
)
const
{
if
(
detail
::
matches
(
data
.
begin
(),
m_pattern
->
begin
()))
{
m_iimpl
.
m_fun
();
return
true
;
}
return
false
;
}
public:
template
<
typename
F
>
...
...
@@ -184,12 +215,12 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
bool
invoke
(
any_tuple
const
&
data
)
const
{
if
(
detail
::
matches
(
data
.
begin
(),
m_pattern
->
begin
()))
{
m_iimpl
.
m_fun
();
return
true
;
}
return
false
;
return
invoke_impl
(
data
);
}
bool
invoke
(
any_tuple_view
const
&
data
)
const
{
return
invoke_impl
(
data
)
;
}
intermediate
*
get_intermediate
(
any_tuple
const
&
data
)
...
...
@@ -200,7 +231,6 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
};
template
<
typename
Fun
,
class
Pattern
>
struct
select_invokable_impl
{
...
...
cppa/detail/matches.hpp
View file @
bcafa1b9
...
...
@@ -78,6 +78,7 @@ template<class MappingVector, typename Iterator>
class
push_mapping_decorator
{
size_t
pos
;
Iterator
iter
;
MappingVector
*
mapping
;
...
...
@@ -86,28 +87,29 @@ class push_mapping_decorator
typedef
MappingVector
mapping_vector
;
push_mapping_decorator
(
Iterator
const
&
i
,
MappingVector
*
mv
)
:
iter
(
i
),
mapping
(
mv
)
:
pos
(
0
),
iter
(
i
),
mapping
(
mv
)
{
}
push_mapping_decorator
(
push_mapping_decorator
const
&
other
,
MappingVector
*
mv
)
:
iter
(
other
.
iter
),
mapping
(
mv
)
push_mapping_decorator
(
push_mapping_decorator
const
&
other
,
MappingVector
*
mv
)
:
pos
(
other
.
pos
),
iter
(
other
.
iter
),
mapping
(
mv
)
{
}
push_mapping_decorator
(
push_mapping_decorator
&&
other
)
:
iter
(
std
::
move
(
other
.
iter
)),
mapping
(
other
.
mapping
)
:
pos
(
other
.
pos
),
iter
(
std
::
move
(
other
.
iter
)),
mapping
(
other
.
mapping
)
{
}
inline
void
next
()
{
iter
.
next
();
}
inline
void
next
()
{
++
pos
;
iter
.
next
();
}
inline
bool
at_end
()
const
{
return
iter
.
at_end
();
}
inline
void
const
*
value
()
const
{
return
iter
.
value
();
}
inline
decltype
(
iter
.
type
())
type
()
const
{
return
iter
.
type
();
}
inline
bool
has_mapping
()
const
{
return
mapping
!=
nullptr
;
}
inline
void
push_mapping
()
{
if
(
mapping
)
mapping
->
push_back
(
iter
.
position
()
);
if
(
mapping
)
mapping
->
push_back
(
pos
);
}
inline
void
push_mapping
(
MappingVector
const
&
mv
)
{
...
...
cppa/detail/types_array.hpp
View file @
bcafa1b9
...
...
@@ -114,6 +114,34 @@ struct types_array : types_array_impl<util::tl_forall<util::type_list<T...>,
util
::
is_builtin
>::
value
,
T
...
>
{
class
const_iterator
{
types_array
const
&
m_ref
;
size_t
m_pos
;
public:
const_iterator
(
const_iterator
const
&
)
=
default
;
const_iterator
&
operator
=
(
const_iterator
const
&
)
=
default
;
const_iterator
(
types_array
const
&
ptr
)
:
m_ref
(
ptr
),
m_pos
(
0
)
{
}
inline
void
next
()
{
++
m_pos
;
}
inline
bool
at_end
()
const
{
return
m_pos
==
sizeof
...(
T
);
}
inline
uniform_type_info
const
*
type
()
const
{
return
m_ref
[
m_pos
];
}
inline
bool
has_value
()
const
{
return
false
;
}
inline
void
const
*
value
()
const
{
return
nullptr
;
}
};
const_iterator
begin
()
const
{
return
{
*
this
};
}
};
template
<
typename
...
T
>
...
...
cppa/invoke_rules.hpp
View file @
bcafa1b9
...
...
@@ -50,6 +50,7 @@ namespace cppa {
class
any_tuple
;
class
invoke_rules
;
class
any_tuple_view
;
class
timed_invoke_rules
;
typedef
std
::
list
<
detail
::
invokable_ptr
>
invokable_list
;
...
...
@@ -87,6 +88,8 @@ class invoke_rules_base
*/
bool
operator
()(
any_tuple
const
&
data
)
const
;
bool
operator
()(
any_tuple_view
const
&
data
)
const
;
/**
* @brief Tries to match @p data with one of the stored patterns.
* @param data Data tuple that should be matched.
...
...
cppa/
get_view
.hpp
→
cppa/
match
.hpp
View file @
bcafa1b9
...
...
@@ -28,39 +28,65 @@
\******************************************************************************/
#ifndef
GET_VIEW
_HPP
#define
GET_VIEW
_HPP
#ifndef
MATCH
_HPP
#define
MATCH
_HPP
#include <vector>
#include <cstddef>
#include <type_traits>
#include "cppa/tuple.hpp"
#include "cppa/pattern.hpp"
#include "cppa/anything.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/any_tuple_view.hpp"
#include "cppa/util/
tbind
.hpp"
#include "cppa/util/
type_list
.hpp"
#include "cppa/util/
if_else
.hpp"
#include "cppa/util/
enable_if
.hpp"
#include "cppa/detail/
matche
s.hpp"
#include "cppa/detail/
implicit_conversion
s.hpp"
namespace
cppa
{
template
<
typename
...
MatchRules
>
typename
tuple_view_type_from_type_list
<
typename
util
::
tl_filter_not
<
util
::
type_list
<
MatchRules
...
>
,
util
::
tbind
<
std
::
is_same
,
anything
>::
type
>::
type
>::
type
get_view
(
any_tuple
const
&
ut
)
namespace
detail
{
template
<
typename
Tuple
>
struct
match_helper
{
pattern
<
MatchRules
...
>
p
;
typename
pattern
<
MatchRules
...
>::
mapping_vector
mapping
;
if
(
detail
::
matches
(
detail
::
pm_decorated
(
ut
.
begin
(),
&
mapping
),
p
.
begin
()))
static
constexpr
bool
is_view
=
std
::
is_same
<
Tuple
,
any_tuple_view
>::
value
;
Tuple
what
;
template
<
typename
T
>
match_helper
(
T
const
&
w
,
typename
util
::
enable_if_c
<
std
::
is_same
<
T
,
T
>::
value
&&
is_view
>::
type
*
=
0
)
:
what
(
w
)
{
}
template
<
typename
T
>
match_helper
(
T
const
&
w
,
typename
util
::
enable_if_c
<
std
::
is_same
<
T
,
T
>::
value
&&
!
is_view
>::
type
*
=
0
)
:
what
(
make_tuple
(
w
))
{
}
void
operator
()(
invoke_rules
&
rules
)
{
rules
(
what
);
}
void
operator
()(
invoke_rules
&&
rules
)
{
rules
(
what
);
}
template
<
typename
Head
,
typename
...
Tail
>
void
operator
()(
invoke_rules
&&
bhvr
,
Head
&&
head
,
Tail
&&
...
tail
)
{
invoke_rules
tmp
(
std
::
move
(
bhvr
));
(
*
this
)(
tmp
.
splice
(
std
::
forward
<
Head
>
(
head
)),
std
::
forward
<
Tail
>
(
tail
)...);
}
template
<
typename
Head
,
typename
...
Tail
>
void
operator
()(
invoke_rules
&
bhvr
,
Head
&&
head
,
Tail
&&
...
tail
)
{
return
{
ut
.
vals
(),
mapping
};
(
*
this
)(
bhvr
.
splice
(
std
::
forward
<
Head
>
(
head
)),
std
::
forward
<
Tail
>
(
tail
)...);
}
// todo: throw nicer exception
throw
std
::
runtime_error
(
"doesn't match"
);
};
}
// namespace detail
template
<
typename
T
>
auto
match
(
T
const
&
x
)
->
detail
::
match_helper
<
typename
util
::
if_else
<
std
::
is_same
<
typename
detail
::
implicit_conversions
<
T
>::
type
,
T
>
,
any_tuple_view
,
util
::
wrapped
<
any_tuple
>
>::
type
>
{
return
{
x
};
}
}
// namespace cppa
#endif //
GET_VIEW
_HPP
#endif //
MATCH
_HPP
cppa/option.hpp
View file @
bcafa1b9
...
...
@@ -33,31 +33,33 @@
namespace
cppa
{
template
<
typename
What
>
template
<
typename
T
>
class
option
{
union
{
What
m_value
;
T
m_value
;
};
bool
m_valid
;
void
destroy
()
{
if
(
m_valid
)
m_value
.
~
What
();
if
(
m_valid
)
m_value
.
~
T
();
}
template
<
typename
V
>
void
cr
(
V
&&
value
)
{
m_valid
=
true
;
new
(
&
m_value
)
What
(
std
::
forward
<
V
>
(
value
));
new
(
&
m_value
)
T
(
std
::
forward
<
V
>
(
value
));
}
public:
typedef
T
value_type
;
option
()
:
m_valid
(
false
)
{
}
template
<
typename
V
>
...
...
@@ -131,14 +133,14 @@ class option
return
*
this
;
}
option
&
operator
=
(
What
const
&
value
)
option
&
operator
=
(
T
const
&
value
)
{
if
(
m_valid
)
m_value
=
value
;
else
cr
(
value
);
return
*
this
;
}
option
&
operator
=
(
What
&
value
)
option
&
operator
=
(
T
&
value
)
{
if
(
m_valid
)
m_value
=
std
::
move
(
value
);
else
cr
(
std
::
move
(
value
));
...
...
@@ -151,20 +153,20 @@ class option
inline
bool
operator
!
()
const
{
return
!
m_valid
;
}
inline
What
&
operator
*
()
{
return
m_value
;
}
inline
What
const
&
operator
*
()
const
{
return
m_value
;
}
inline
T
&
operator
*
()
{
return
m_value
;
}
inline
T
const
&
operator
*
()
const
{
return
m_value
;
}
inline
What
&
get
()
{
return
m_value
;
}
inline
T
&
get
()
{
return
m_value
;
}
inline
What
const
&
get
()
const
{
return
m_value
;
}
inline
T
const
&
get
()
const
{
return
m_value
;
}
inline
What
&
get_or_else
(
What
const
&
val
)
inline
T
&
get_or_else
(
T
const
&
val
)
{
if
(
!
m_valid
)
cr
(
val
);
return
m_value
;
}
inline
What
&
get_or_else
(
What
&&
val
)
inline
T
&
get_or_else
(
T
&&
val
)
{
if
(
!
m_valid
)
cr
(
std
::
move
(
val
));
return
m_value
;
...
...
cppa/pattern.hpp
View file @
bcafa1b9
...
...
@@ -31,18 +31,22 @@
#ifndef LIBCPPA_PATTERN_HPP
#define LIBCPPA_PATTERN_HPP
#include <list>
#include <vector>
#include <cstddef>
#include <type_traits>
#include "cppa/option.hpp"
#include "cppa/anything.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/arg_match_t.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/is_primitive.hpp"
#include "cppa/detail/boxed.hpp"
#include "cppa/detail/tdata.hpp"
...
...
@@ -84,22 +88,13 @@ class pattern
public:
const_iterator
(
pattern
const
*
ptr
)
:
m_ptr
(
ptr
),
m_pos
(
0
)
{
}
const_iterator
(
const_iterator
const
&
)
=
default
;
const_iterator
&
operator
=
(
const_iterator
const
&
)
=
default
;
const_iterator
(
pattern
const
*
ptr
)
:
m_ptr
(
ptr
),
m_pos
(
0
)
{
}
const_iterator
&
next
()
{
++
m_pos
;
return
*
this
;
}
inline
void
next
()
{
++
m_pos
;
}
inline
bool
at_end
()
{
return
m_pos
==
sizeof
...(
Types
);
}
inline
bool
at_end
()
{
return
m_pos
==
sizeof
...(
Types
);
}
inline
uniform_type_info
const
*
type
()
const
{
...
...
cppa/to_string.hpp
View file @
bcafa1b9
...
...
@@ -32,6 +32,7 @@
#define TO_STRING_HPP
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/to_uniform_name.hpp"
namespace
cppa
{
...
...
cppa/tuple.hpp
View file @
bcafa1b9
...
...
@@ -42,12 +42,14 @@
#include "cppa/ref_counted.hpp"
#include "cppa/util/at.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/replace_type.hpp"
#include "cppa/util/is_comparable.hpp"
#include "cppa/util/compare_tuples.hpp"
#include "cppa/util/is_legal_tuple_type.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/decorated_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace
cppa
{
...
...
@@ -84,6 +86,8 @@ class tuple
public:
static
constexpr
size_t
num_elements
=
sizeof
...(
ElementTypes
);
/**
* @brief Initializes each element with its default constructor.
*/
...
...
@@ -122,6 +126,13 @@ class tuple
return
tuple
(
ptr_ctor
(),
ptr
);
}
static
tuple
from
(
cow_ptr
<
detail
::
abstract_tuple
>
const
&
ptr
,
util
::
fixed_vector
<
size_t
,
num_elements
>
const
&
mv
)
{
return
tuple
(
ptr_ctor
(),
new
detail
::
decorated_tuple
<
num_elements
>
(
ptr
,
mv
));
}
/**
* @brief Gets the size of this tuple.
* @returns <tt>sizeof...(ElementTypes)</tt>.
...
...
@@ -150,7 +161,7 @@ class tuple
* of an element.
* @returns The uniform type of the <tt>N</tt>th element.
*/
inline
uniform_type_info
const
*
u
type_at
(
size_t
p
)
const
inline
uniform_type_info
const
*
type_at
(
size_t
p
)
const
{
return
m_vals
->
type_at
(
p
);
}
...
...
cppa/tuple_cast.hpp
View file @
bcafa1b9
...
...
@@ -31,54 +31,128 @@
#ifndef TUPLE_CAST_HPP
#define TUPLE_CAST_HPP
#include <type_traits>
#include "cppa/option.hpp"
#include "cppa/pattern.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/any_tuple_view.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/decorated_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace
cppa
{
// cast using a pattern
template
<
typename
...
P
>
auto
tuple_cast
(
any_tuple
const
&
tup
,
pattern
<
P
...
>
const
&
p
)
->
option
<
typename
tuple_from_type_list
<
typename
pattern
<
P
...
>::
filtered_types
>::
type
>
template
<
class
ResultTuple
,
class
Tuple
,
typename
...
P
>
option
<
ResultTuple
>
tuple_cast_impl
(
Tuple
const
&
tup
,
pattern
<
P
...
>
const
&
p
)
{
typedef
typename
pattern
<
P
...
>::
mapping_vector
mapping_vector
;
typedef
typename
pattern
<
P
...
>::
filtered_types
filtered_types
;
typedef
typename
tuple_from_type_list
<
filtered_types
>::
type
tuple_type
;
option
<
tuple_type
>
result
;
mapping_vector
mv
;
typename
pattern
<
P
...
>::
mapping_vector
mv
;
if
(
detail
::
matches
(
detail
::
pm_decorated
(
tup
.
begin
(),
&
mv
),
p
.
begin
()))
{
if
(
mv
.
size
()
==
tup
.
size
())
// perfect match
{
re
sult
=
tuple_type
::
from
(
tup
.
vals
())
;
re
turn
{
ResultTuple
::
from
(
tup
.
vals
())}
;
}
else
{
result
=
tuple_type
::
from
(
new
detail
::
decorated_tuple
<
filtered_types
::
size
>
(
tup
.
vals
(),
mv
));
typedef
detail
::
decorated_tuple
<
filtered_types
::
size
>
decorated
;
return
{
ResultTuple
::
from
(
tup
.
vals
(),
mv
)};
}
}
return
std
::
move
(
result
)
;
return
{
}
;
}
// cast using types
template
<
typename
...
T
>
option
<
tuple
<
T
...
>
>
tuple_cast
(
any_t
uple
const
&
tup
)
template
<
class
ResultTuple
,
class
Tuple
,
typename
...
T
>
option
<
ResultTuple
>
tuple_cast_impl
(
T
uple
const
&
tup
)
{
option
<
tuple
<
T
...
>
>
result
;
auto
&
tarr
=
detail
::
static_types_array
<
T
...
>::
arr
;
if
(
tup
.
size
()
==
sizeof
...(
T
))
// no anything in given template parameter pack
if
(
ResultTuple
::
num_elements
==
sizeof
...(
T
))
{
auto
&
tarr
=
detail
::
static_types_array
<
T
...
>::
arr
;
if
(
tup
.
size
()
==
sizeof
...(
T
))
{
for
(
size_t
i
=
0
;
i
<
sizeof
...(
T
);
++
i
)
{
if
(
tarr
[
i
]
!=
tup
.
type_at
(
i
))
return
{
};
}
// always a perfect match
return
{
ResultTuple
::
from
(
tup
.
vals
())};
}
}
else
{
for
(
size_t
i
=
0
;
i
<
sizeof
...(
T
);
++
i
)
util
::
fixed_vector
<
size_t
,
ResultTuple
::
num_elements
>
mv
;
if
(
detail
::
matches
(
detail
::
pm_decorated
(
tup
.
begin
(),
&
mv
),
detail
::
static_types_array
<
T
...
>::
arr
.
begin
()))
{
if
(
tarr
[
i
]
!=
tup
.
type_at
(
i
))
return
std
::
move
(
result
);
// never a perfect match
typedef
detail
::
decorated_tuple
<
ResultTuple
::
num_elements
>
decorated
;
return
{
ResultTuple
::
from
(
tup
.
vals
(),
mv
)};
}
result
=
tuple
<
T
...
>::
from
(
tup
.
vals
());
}
return
std
::
move
(
result
);;
return
{
};
}
// cast using a pattern
template
<
typename
...
P
>
auto
tuple_cast
(
any_tuple
const
&
tup
,
pattern
<
P
...
>
const
&
p
)
->
option
<
typename
tuple_from_type_list
<
typename
pattern
<
P
...
>::
filtered_types
>::
type
>
{
typedef
typename
pattern
<
P
...
>::
filtered_types
filtered_types
;
typedef
typename
tuple_from_type_list
<
filtered_types
>::
type
tuple_type
;
return
tuple_cast_impl
<
tuple_type
,
any_tuple
,
P
...
>
(
tup
,
p
);
}
// cast using types
template
<
typename
...
T
>
auto
tuple_cast
(
any_tuple
const
&
tup
)
->
option
<
typename
tuple_from_type_list
<
typename
util
::
tl_filter_not
<
util
::
type_list
<
T
...
>
,
util
::
tbind
<
std
::
is_same
,
anything
>::
type
>::
type
>::
type
>
{
typedef
decltype
(
tuple_cast
<
T
...
>
(
tup
))
result_type
;
typedef
typename
result_type
::
value_type
tuple_type
;
return
tuple_cast_impl
<
tuple_type
,
any_tuple
,
T
...
>
(
tup
);
}
template
<
typename
...
P
>
auto
tuple_cast
(
any_tuple_view
const
&
tup
,
pattern
<
P
...
>
const
&
p
)
->
option
<
typename
tuple_view_from_type_list
<
typename
pattern
<
P
...
>::
filtered_types
>::
type
>
{
typedef
typename
pattern
<
P
...
>::
filtered_types
filtered_types
;
typedef
typename
tuple_view_from_type_list
<
filtered_types
>::
type
tuple_type
;
return
tuple_cast_impl
<
tuple_type
,
any_tuple_view
,
P
...
>
(
tup
,
p
);
}
// cast using types
template
<
typename
...
T
>
auto
tuple_cast
(
any_tuple_view
const
&
tup
)
->
option
<
typename
tuple_view_from_type_list
<
typename
util
::
tl_filter_not
<
util
::
type_list
<
T
...
>
,
util
::
tbind
<
std
::
is_same
,
anything
>::
type
>::
type
>::
type
>
{
typedef
decltype
(
tuple_cast
<
T
...
>
(
tup
))
result_type
;
typedef
typename
result_type
::
value_type
tuple_type
;
return
tuple_cast_impl
<
tuple_type
,
any_tuple_view
,
T
...
>
(
tup
);
}
}
// namespace cppa
...
...
cppa/tuple_view.hpp
View file @
bcafa1b9
...
...
@@ -32,9 +32,11 @@
#define TUPLE_VIEW_HPP
#include <vector>
#include <cstring>
#include "cppa/get.hpp"
#include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/util/at.hpp"
#include "cppa/util/type_list.hpp"
...
...
@@ -58,52 +60,45 @@ class tuple_view
template
<
size_t
N
,
typename
...
Types
>
friend
typename
util
::
at
<
N
,
Types
...
>::
type
&
get_ref
(
tuple_view
<
Types
...
>&
);
public:
typedef
cow_ptr
<
detail
::
abstract_tuple
>
vals_t
;
static
constexpr
size_t
num_elements
=
sizeof
...(
ElementTypes
);
void
const
*
m_data
[
sizeof
...(
ElementTypes
)];
t
ypedef
util
::
fixed_vector
<
size_t
,
num_elements
>
mapping_vector
;
t
uple_view
()
{
}
tuple_view
()
:
m_vals
(
tuple
<
ElementTypes
...
>
().
vals
())
{
}
static
tuple_view
from
(
vals_t
const
&
vals
)
{
return
tuple_view
(
vals
);
}
public:
static
tuple_view
from
(
vals_t
&&
vals
)
{
return
tuple_view
(
std
::
move
(
vals
));
}
static
constexpr
size_t
num_elements
=
sizeof
...(
ElementTypes
);
tuple_view
(
vals_t
const
&
vals
,
mapping_vector
&
mapping
)
:
m_vals
(
new
detail
::
decorated_tuple
<
num_elements
>
(
vals
,
mapping
))
static
tuple_view
from
(
std
::
vector
<
std
::
pair
<
uniform_type_info
const
*
,
void
const
*>
>
const
&
vec
)
{
tuple_view
result
;
size_t
j
=
0
;
for
(
auto
i
=
vec
.
begin
();
i
!=
vec
.
end
();
++
i
)
{
result
.
m_data
[
j
++
]
=
i
->
second
;
}
return
std
::
move
(
result
);
}
tuple_view
(
tuple_view
&&
other
)
:
m_vals
(
std
::
move
(
other
.
m_vals
))
static
tuple_view
from
(
std
::
vector
<
std
::
pair
<
uniform_type_info
const
*
,
void
const
*>
>
const
&
vec
,
util
::
fixed_vector
<
size_t
,
sizeof
...(
ElementTypes
)
>
const
&
mv
)
{
tuple_view
result
;
for
(
size_t
i
=
0
;
i
<
sizeof
...(
ElementTypes
);
++
i
)
{
result
.
m_data
[
i
]
=
vec
[
mv
[
i
]].
second
;
}
return
std
::
move
(
result
);
}
tuple_view
&
operator
=
(
tuple_view
const
&
other
)
{
m_vals
=
other
.
m_vals
;
return
*
this
;
}
tuple_view
&
operator
=
(
tuple_view
&&
other
)
{
m_vals
=
std
::
move
(
other
.
m_vals
);
memcpy
(
m_data
,
other
.
m_data
,
num_elements
*
sizeof
(
void
*
));
return
*
this
;
}
tuple_view
(
tuple_view
const
&
)
=
default
;
inline
vals_t
const
&
vals
()
const
tuple_view
(
tuple_view
const
&
other
)
{
return
m_vals
;
memcpy
(
m_data
,
other
.
m_data
,
num_elements
*
sizeof
(
void
*
))
;
}
inline
size_t
size
()
const
...
...
@@ -111,17 +106,7 @@ class tuple_view
return
sizeof
...(
ElementTypes
);
}
private:
explicit
tuple_view
(
vals_t
const
&
vals
)
:
m_vals
(
vals
)
{
}
explicit
tuple_view
(
vals_t
&&
vals
)
:
m_vals
(
std
::
move
(
vals
))
{
}
vals_t
m_vals
;
inline
void
const
*
at
(
size_t
p
)
const
{
return
m_data
[
p
];
}
};
...
...
@@ -130,22 +115,22 @@ const typename util::at<N, Types...>::type& get(tuple_view<Types...> const& t)
{
static_assert
(
N
<
sizeof
...(
Types
),
"N >= t.size()"
);
typedef
typename
util
::
at
<
N
,
Types
...
>::
type
result_t
;
return
*
reinterpret_cast
<
result_t
const
*>
(
t
.
vals
()
->
at
(
N
));
return
*
reinterpret_cast
<
result_t
const
*>
(
t
.
at
(
N
));
}
template
<
size_t
N
,
typename
...
Types
>
typename
util
::
at
<
N
,
Types
...
>::
type
&
get_ref
(
tuple_view
<
Types
...
>&
t
)
{
static_assert
(
N
<
sizeof
...(
Types
),
"N >= t.size()"
);
typedef
typename
util
::
at
<
N
,
Types
...
>::
type
result_t
;
return
*
reinterpret_cast
<
result_t
*>
(
t
.
m_vals
->
mutable_at
(
N
));
}
//
template<size_t N, typename... Types>
//
typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>& t)
//
{
//
static_assert(N < sizeof...(Types), "N >= t.size()");
//
typedef typename util::at<N, Types...>::type result_t;
//
return *reinterpret_cast<result_t*>(t.m_vals->mutable_at(N));
//
}
template
<
typename
TypeList
>
struct
tuple_view_
type_
from_type_list
;
struct
tuple_view_from_type_list
;
template
<
typename
...
Types
>
struct
tuple_view_
type_
from_type_list
<
util
::
type_list
<
Types
...
>>
struct
tuple_view_from_type_list
<
util
::
type_list
<
Types
...
>>
{
typedef
tuple_view
<
Types
...
>
type
;
};
...
...
src/any_tuple.cpp
View file @
bcafa1b9
...
...
@@ -39,7 +39,7 @@ struct offset_decorator : cppa::detail::abstract_tuple
typedef
cppa
::
cow_ptr
<
cppa
::
detail
::
abstract_tuple
>
ptr_type
;
offset_decorator
(
const
ptr_type
&
decorated
,
size_t
offset
)
offset_decorator
(
ptr_type
const
&
decorated
,
size_t
offset
)
:
m_offset
(
offset
)
,
m_decorated
(
decorated
)
{
...
...
@@ -99,7 +99,7 @@ any_tuple::any_tuple(any_tuple&& other) : m_vals(s_empty_tuple())
m_vals
.
swap
(
other
.
m_vals
);
}
any_tuple
::
any_tuple
(
co
nst
cow_ptr
<
detail
::
abstract_tuple
>
&
vals
)
:
m_vals
(
vals
)
any_tuple
::
any_tuple
(
co
w_ptr
<
detail
::
abstract_tuple
>
const
&
vals
)
:
m_vals
(
vals
)
{
}
...
...
@@ -141,7 +141,7 @@ const cow_ptr<detail::abstract_tuple>& any_tuple::vals() const
return
m_vals
;
}
bool
any_tuple
::
equals
(
const
any_tuple
&
other
)
const
bool
any_tuple
::
equals
(
any_tuple
const
&
other
)
const
{
return
m_vals
->
equals
(
*
other
.
vals
());
}
...
...
src/invoke_rules.cpp
View file @
bcafa1b9
...
...
@@ -46,11 +46,20 @@ invoke_rules_base::~invoke_rules_base()
{
}
bool
invoke_rules_base
::
operator
()(
const
any_tuple
&
t
)
const
bool
invoke_rules_base
::
operator
()(
const
any_tuple
&
data
)
const
{
for
(
auto
i
=
m_list
.
begin
();
i
!=
m_list
.
end
();
++
i
)
for
(
detail
::
invokable_ptr
const
&
ptr
:
m_list
)
{
if
((
*
i
)
->
invoke
(
t
))
return
true
;
if
(
ptr
->
invoke
(
data
))
return
true
;
}
return
false
;
}
bool
invoke_rules_base
::
operator
()(
any_tuple_view
const
&
data
)
const
{
for
(
detail
::
invokable_ptr
const
&
ptr
:
m_list
)
{
if
(
ptr
->
invoke
(
data
))
return
true
;
}
return
false
;
}
...
...
@@ -59,9 +68,9 @@ detail::intermediate*
invoke_rules_base
::
get_intermediate
(
const
any_tuple
&
t
)
const
{
detail
::
intermediate
*
result
;
for
(
auto
i
=
m_list
.
begin
();
i
!=
m_list
.
end
();
++
i
)
for
(
detail
::
invokable_ptr
const
&
ptr
:
m_list
)
{
result
=
(
*
i
)
->
get_intermediate
(
t
);
result
=
ptr
->
get_intermediate
(
t
);
if
(
result
!=
nullptr
)
return
result
;
}
return
nullptr
;
...
...
unit_testing/test__pattern.cpp
View file @
bcafa1b9
...
...
@@ -6,6 +6,7 @@
#include "cppa/on.hpp"
#include "cppa/atom.hpp"
#include "cppa/tuple.hpp"
#include "cppa/match.hpp"
#include "cppa/option.hpp"
#include "cppa/pattern.hpp"
#include "cppa/announce.hpp"
...
...
@@ -42,37 +43,29 @@ typedef std::pair<int,int> foobar;
static
detail
::
types_array
<
int
,
anything
,
float
>
arr1
;
static
detail
::
types_array
<
int
,
anything
,
foobar
>
arr2
;
struct
match_helper
template
<
typename
T
>
void
match_test
(
T
const
&
value
)
{
any_tuple
const
&
what
;
match_helper
(
any_tuple
const
&
w
)
:
what
(
w
)
{
}
void
operator
()(
invoke_rules
&&
rules
)
{
rules
(
what
);
}
};
using
namespace
cppa
::
util
;
match_helper
match
(
any_tuple
const
&
x
)
{
return
{
x
};
match
(
value
)
(
on
<
int
,
int
,
int
,
anything
>
()
>>
[
&
](
int
a
,
int
b
,
int
c
)
{
cout
<<
"("
<<
a
<<
", "
<<
b
<<
", "
<<
c
<<
")"
<<
endl
;
},
on_arg_match
>>
[
&
](
std
::
string
const
&
str
)
{
cout
<<
str
<<
endl
;
}
);
}
size_t
test__pattern
()
{
CPPA_TEST
(
test__pattern
);
match
(
make_tuple
(
1
,
2
,
3
))
(
on_arg_match
>>
[
&
](
int
a
,
int
b
,
int
c
)
{
CPPA_CHECK_EQUAL
(
a
,
1
);
CPPA_CHECK_EQUAL
(
b
,
2
);
CPPA_CHECK_EQUAL
(
c
,
3
);
}
);
match_test
(
make_tuple
(
1
,
2
,
3
));
match_test
(
std
::
list
<
int
>
{
1
,
2
,
3
});
match_test
(
"abc"
);
pattern
<
int
,
anything
,
int
>
i3
;
any_tuple
i3_any_tup
=
make_tuple
(
1
,
2
,
3
);
...
...
unit_testing/test__tuple.cpp
View file @
bcafa1b9
...
...
@@ -11,6 +11,7 @@
#include "cppa/on.hpp"
#include "cppa/util.hpp"
#include "cppa/tuple.hpp"
#include "cppa/pattern.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/to_string.hpp"
#include "cppa/tuple_cast.hpp"
...
...
@@ -38,24 +39,37 @@ size_t test__tuple()
CPPA_CHECK
((
std
::
is_same
<
decltype
(
t0_1
),
int
>::
value
));
CPPA_CHECK_EQUAL
(
t0_0
,
"1"
);
CPPA_CHECK_EQUAL
(
t0_1
,
2
);
// create a view of t0 that only contains the string
auto
v0opt
=
tuple_cast
(
t0
,
pattern
<
std
::
string
,
anything
>
());
if
(
!
v0opt
)
throw
std
::
runtime_error
(
"tuple_cast failed!"
);
auto
&
v0
=
*
v0opt
;
auto
v0_0
=
get
<
0
>
(
v0
);
CPPA_CHECK_EQUAL
(
v0
.
size
(),
1
);
CPPA_CHECK
((
std
::
is_same
<
decltype
(
v0_0
),
std
::
string
>::
value
));
CPPA_CHECK_EQUAL
(
v0_0
,
"1"
);
// check cow semantics
CPPA_CHECK_EQUAL
(
&
get
<
0
>
(
t0
),
&
get
<
0
>
(
v0
));
// point to the same string
get_ref
<
0
>
(
t0
)
=
"hello world"
;
// detaches t0 from v0
CPPA_CHECK_EQUAL
(
get
<
0
>
(
t0
),
"hello world"
);
// t0 contains new value
CPPA_CHECK_EQUAL
(
get
<
0
>
(
v0
),
"1"
);
// v0 contains old value
CPPA_CHECK_NOT_EQUAL
(
&
get
<
0
>
(
t0
),
&
get
<
0
>
(
v0
));
// no longer the same
// check operator==
auto
lhs
=
make_tuple
(
1
,
2
,
3
,
4
);
auto
rhs
=
make_tuple
(
static_cast
<
std
::
uint8_t
>
(
1
),
2.0
,
3
,
4
);
CPPA_CHECK_EQUAL
(
lhs
,
rhs
);
CPPA_CHECK_EQUAL
(
rhs
,
lhs
);
// get a view of t0
auto
v1opt
=
tuple_cast
<
std
::
string
,
anything
>
(
any_tuple_view
(
t0
));
CPPA_CHECK
((
v1opt
));
if
(
v1opt
)
{
auto
&
v1
=
*
v1opt
;
auto
v1_0
=
get
<
0
>
(
v1
);
CPPA_CHECK_EQUAL
(
v1
.
size
(),
1
);
CPPA_CHECK_EQUAL
(
v1_0
,
"1"
);
}
// use tuple cast to get a subtuple
auto
v0opt
=
tuple_cast
<
std
::
string
,
anything
>
(
t0
);
CPPA_CHECK
((
v0opt
));
if
(
v0opt
)
{
auto
&
v0
=
*
v0opt
;
auto
v0_0
=
get
<
0
>
(
v0
);
CPPA_CHECK
((
std
::
is_same
<
decltype
(
v0_0
),
std
::
string
>::
value
));
CPPA_CHECK_EQUAL
(
v0
.
size
(),
1
);
CPPA_CHECK_EQUAL
(
v0_0
,
"1"
);
// check cow semantics
CPPA_CHECK_EQUAL
(
&
get
<
0
>
(
t0
),
&
get
<
0
>
(
v0
));
// point to the same string
get_ref
<
0
>
(
t0
)
=
"hello world"
;
// detaches t0 from v0
CPPA_CHECK_EQUAL
(
get
<
0
>
(
t0
),
"hello world"
);
// t0 contains new value
CPPA_CHECK_EQUAL
(
get
<
0
>
(
v0
),
"1"
);
// v0 contains old value
CPPA_CHECK_NOT_EQUAL
(
&
get
<
0
>
(
t0
),
&
get
<
0
>
(
v0
));
// no longer the same
// check operator==
auto
lhs
=
make_tuple
(
1
,
2
,
3
,
4
);
auto
rhs
=
make_tuple
(
static_cast
<
std
::
uint8_t
>
(
1
),
2.0
,
3
,
4
);
CPPA_CHECK_EQUAL
(
lhs
,
rhs
);
CPPA_CHECK_EQUAL
(
rhs
,
lhs
);
}
return
CPPA_TEST_RESULT
;
}
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