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
a8c7dd29
Commit
a8c7dd29
authored
Feb 09, 2018
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/multi-variant-visit'
parents
58fc8dd8
3890119e
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
114 additions
and
49 deletions
+114
-49
libcaf_core/caf/fwd.hpp
libcaf_core/caf/fwd.hpp
+1
-0
libcaf_core/caf/variant.hpp
libcaf_core/caf/variant.hpp
+91
-49
libcaf_core/test/variant.cpp
libcaf_core/test/variant.cpp
+22
-0
No files found.
libcaf_core/caf/fwd.hpp
View file @
a8c7dd29
...
...
@@ -48,6 +48,7 @@ template <class, class, class> class random_topic_scatterer;
// -- variadic templates -------------------------------------------------------
template
<
class
...
>
class
result
;
template
<
class
...
>
class
variant
;
template
<
class
...
>
class
delegated
;
template
<
class
...
>
class
typed_actor
;
template
<
class
...
>
class
typed_actor_pointer
;
...
...
libcaf_core/caf/variant.hpp
View file @
a8c7dd29
...
...
@@ -22,6 +22,7 @@
#include <type_traits>
#include "caf/config.hpp"
#include "caf/fwd.hpp"
#include "caf/static_visitor.hpp"
#include "caf/meta/omittable.hpp"
...
...
@@ -32,7 +33,15 @@
#define CAF_VARIANT_CASE(n) \
case n: \
return f(x.get(std::integral_constant<int, (n <= max_type_id ? n : 0)>()))
return f(std::forward<Us>(xs)..., \
x.get(std::integral_constant<int, (n <= max_type_id ? n : 0)>()))
#define CAF_VARIANT_DISPATCH_CASE(n) \
case n: \
return next.template apply_impl<Result>( \
std::forward<Variant>(next), std::forward<Visitor>(f), \
std::forward<Us>(xs)..., \
x.get(std::integral_constant<int, (n <= max_type_id ? n : 0)>()))
#define CAF_VARIANT_ASSIGN_CASE(n) \
case n: { \
...
...
@@ -48,6 +57,10 @@ namespace caf {
constexpr
size_t
variant_npos
=
static_cast
<
size_t
>
(
-
1
);
struct
variant_marker_t
{};
constexpr
variant_marker_t
variant_marker
=
variant_marker_t
{};
template
<
class
T
>
struct
variant_assign_helper
{
using
result_type
=
void
;
...
...
@@ -70,6 +83,17 @@ struct variant_move_helper {
}
};
template
<
class
F
,
class
...
Ts
>
struct
variant_visit_result
{
using
type
=
decltype
((
std
::
declval
<
F
&>
())(
std
::
declval
<
typename
Ts
::
type0
&>
()...));
};
template
<
class
F
,
class
...
Ts
>
using
variant_visit_result_t
=
typename
variant_visit_result
<
detail
::
decay_t
<
F
>
,
detail
::
decay_t
<
Ts
>
...
>::
type
;
template
<
class
T
,
class
U
,
bool
Enable
=
std
::
is_integral
<
T
>
::
value
&&
std
::
is_integral
<
U
>::
value
...
...
@@ -95,6 +119,21 @@ struct is_same_ish
is_equal_int_type
<
T
,
U
>
>::
type
{
};
template
<
class
T
>
struct
is_variant
:
std
::
false_type
{};
template
<
class
...
Ts
>
struct
is_variant
<
variant
<
Ts
...
>>
:
std
::
true_type
{};
template
<
class
...
Ts
>
struct
is_variant
<
variant
<
Ts
...
>&>
:
std
::
true_type
{};
template
<
class
...
Ts
>
struct
is_variant
<
const
variant
<
Ts
...
>&>
:
std
::
true_type
{};
template
<
class
...
Ts
>
struct
is_variant
<
const
variant
<
Ts
...
>&&>
:
std
::
true_type
{};
/// A variant represents always a valid value of one of the types `Ts...`.
template
<
class
...
Ts
>
class
variant
{
...
...
@@ -114,13 +153,13 @@ public:
variant
&
operator
=
(
const
variant
&
other
)
{
variant_assign_helper
<
variant
>
helper
{
*
this
};
other
.
apply
(
helper
);
other
.
template
apply
<
void
>
(
helper
);
return
*
this
;
}
variant
&
operator
=
(
variant
&&
other
)
{
variant_move_helper
<
variant
>
helper
{
*
this
};
other
.
apply
(
helper
);
other
.
template
apply
<
void
>
(
helper
);
return
*
this
;
}
...
...
@@ -144,12 +183,12 @@ public:
variant
(
const
variant
&
other
)
:
type_
(
variant_npos
)
{
variant_assign_helper
<
variant
>
helper
{
*
this
};
other
.
apply
(
helper
);
other
.
template
apply
<
void
>
(
helper
);
}
variant
(
variant
&&
other
)
:
type_
(
variant_npos
)
{
variant_move_helper
<
variant
>
helper
{
*
this
};
other
.
apply
(
helper
);
other
.
template
apply
<
void
>
(
helper
);
}
~
variant
()
{
...
...
@@ -191,21 +230,20 @@ public:
return
data_
.
get
(
token
);
}
template
<
class
Visitor
>
auto
apply
(
Visitor
&&
visitor
)
const
->
decltype
(
visitor
(
std
::
declval
<
const
type0
&>
()))
{
return
apply_impl
(
*
this
,
std
::
forward
<
Visitor
>
(
visitor
)
);
template
<
class
Result
,
class
Visitor
,
class
...
Variants
>
Result
apply
(
Visitor
&&
visitor
,
Variants
&&
...
xs
)
const
{
return
apply_impl
<
Result
>
(
*
this
,
std
::
forward
<
Visitor
>
(
visitor
),
std
::
forward
<
Variants
>
(
xs
)...,
variant_marker
);
}
template
<
class
Visitor
>
auto
apply
(
Visitor
&&
visitor
)
->
decltype
(
visitor
(
std
::
declval
<
type0
&>
()))
{
return
apply_impl
(
*
this
,
std
::
forward
<
Visitor
>
(
visitor
));
template
<
class
Result
,
class
Visitor
,
class
...
Variants
>
Result
apply
(
Visitor
&&
visitor
,
Variants
&&
...
xs
)
{
return
apply_impl
<
Result
>
(
*
this
,
std
::
forward
<
Visitor
>
(
visitor
),
std
::
forward
<
Variants
>
(
xs
)...,
variant_marker
);
}
template
<
class
Self
,
class
Visitor
>
static
auto
apply_impl
(
Self
&
x
,
Visitor
&&
f
)
->
decltype
(
f
(
std
::
declval
<
typename
std
::
conditional
<
std
::
is_const
<
Self
>::
value
,
const
type0
,
type0
>::
type
&>
()))
{
template
<
class
Result
,
class
Self
,
class
Visitor
,
class
...
Us
>
static
Result
apply_impl
(
Self
&
x
,
Visitor
&&
f
,
variant_marker_t
,
Us
&&
...
xs
)
{
switch
(
x
.
type_
)
{
default:
CAF_RAISE_ERROR
(
"invalid type found"
);
CAF_VARIANT_CASE
(
0
);
...
...
@@ -230,13 +268,41 @@ public:
CAF_VARIANT_CASE
(
19
);
}
}
template
<
class
Result
,
class
Self
,
class
Visitor
,
class
Variant
,
class
...
Us
>
static
detail
::
enable_if_t
<
is_variant
<
Variant
>::
value
,
Result
>
apply_impl
(
Self
&
x
,
Visitor
&&
f
,
Variant
&&
next
,
Us
&&
...
xs
)
{
switch
(
x
.
type_
)
{
default:
CAF_RAISE_ERROR
(
"invalid type found"
);
CAF_VARIANT_DISPATCH_CASE
(
0
);
CAF_VARIANT_DISPATCH_CASE
(
1
);
CAF_VARIANT_DISPATCH_CASE
(
2
);
CAF_VARIANT_DISPATCH_CASE
(
3
);
CAF_VARIANT_DISPATCH_CASE
(
4
);
CAF_VARIANT_DISPATCH_CASE
(
5
);
CAF_VARIANT_DISPATCH_CASE
(
6
);
CAF_VARIANT_DISPATCH_CASE
(
7
);
CAF_VARIANT_DISPATCH_CASE
(
8
);
CAF_VARIANT_DISPATCH_CASE
(
9
);
CAF_VARIANT_DISPATCH_CASE
(
10
);
CAF_VARIANT_DISPATCH_CASE
(
11
);
CAF_VARIANT_DISPATCH_CASE
(
12
);
CAF_VARIANT_DISPATCH_CASE
(
13
);
CAF_VARIANT_DISPATCH_CASE
(
14
);
CAF_VARIANT_DISPATCH_CASE
(
15
);
CAF_VARIANT_DISPATCH_CASE
(
16
);
CAF_VARIANT_DISPATCH_CASE
(
17
);
CAF_VARIANT_DISPATCH_CASE
(
18
);
CAF_VARIANT_DISPATCH_CASE
(
19
);
}
}
/// @endcond
private:
inline
void
destroy_data
()
{
if
(
type_
==
variant_npos
)
return
;
// nothing to do
detail
::
variant_data_destructor
f
;
apply
(
f
);
apply
<
void
>
(
f
);
}
template
<
class
U
>
...
...
@@ -267,7 +333,7 @@ private:
"unless the element types of A are a strict subset of "
"the element types of B"
);
variant_assign_helper
<
variant
>
helper
{
*
this
};
other
.
apply
(
helper
);
other
.
template
apply
<
void
>
(
helper
);
}
template
<
class
...
Us
>
...
...
@@ -283,19 +349,13 @@ private:
"unless the element types of A are a strict subset of "
"the element types of B"
);
variant_move_helper
<
variant
>
helper
{
*
this
};
other
.
apply
(
helper
);
other
.
template
apply
<
void
>
(
helper
);
}
size_t
type_
;
detail
::
variant_data
<
typename
lift_void
<
Ts
>::
type
...
>
data_
;
};
template
<
class
T
>
struct
is_variant
:
std
::
false_type
{};
template
<
class
...
Ts
>
struct
is_variant
<
variant
<
Ts
...
>>
:
std
::
true_type
{};
/// @relates variant
template
<
class
T
,
class
...
Us
>
T
&
get
(
variant
<
Us
...
>&
value
)
{
...
...
@@ -333,28 +393,11 @@ const T* get_if(const variant<Us...>* value) {
}
/// @relates variant
template
<
class
Visitor
,
class
...
Ts
>
typename
Visitor
::
result_type
CAF_DEPRECATED
apply_visitor
(
Visitor
&
visitor
,
const
variant
<
Ts
...
>&
data
)
{
return
data
.
apply
(
visitor
);
}
/// @relates variant
template
<
class
Visitor
,
class
Variant
,
class
E
=
typename
std
::
enable_if
<
is_variant
<
typename
std
::
decay
<
Variant
>
::
type
>::
value
>::
type
>
auto
visit
(
Visitor
&&
visitor
,
Variant
&&
data
)
->
decltype
(
data
.
apply
(
std
::
forward
<
Visitor
>
(
visitor
)))
{
return
data
.
apply
(
visitor
);
}
/// @relates variant
template
<
class
Visitor
,
class
...
Ts
>
typename
Visitor
::
result_type
CAF_DEPRECATED
apply_visitor
(
Visitor
&
visitor
,
variant
<
Ts
...
>&
data
)
{
return
data
.
apply
(
visitor
);
template
<
class
Visitor
,
class
Variant
,
class
...
Variants
,
class
Result
=
variant_visit_result_t
<
Visitor
,
Variant
,
Variants
...>
>
Result
visit
(
Visitor
&&
f
,
Variant
&&
x
,
Variants
&&
...
xs
)
{
return
x
.
template
apply
<
Result
>(
std
::
forward
<
Visitor
>
(
f
),
std
::
forward
<
Variants
>
(
xs
)...);
}
template
<
class
T
,
class
...
Ts
>
...
...
@@ -408,8 +451,7 @@ struct variant_reader {
template
<
class
Inspector
,
class
...
Ts
>
typename
Inspector
::
result_type
inspect
(
Inspector
&
f
,
variant_reader
<
variant
<
Ts
...
>>&
x
)
{
return
x
.
x
.
apply
(
f
);
//return variant<Ts...>::apply_impl(x.x, f);
return
x
.
x
.
template
apply
<
typename
Inspector
::
result_type
>(
f
);
}
/// @relates variant
...
...
libcaf_core/test/variant.cpp
View file @
a8c7dd29
...
...
@@ -127,3 +127,25 @@ CAF_TEST(copying_moving_roundtrips) {
macro_repeat20
(
v20_test
);
}
namespace
{
struct
test_visitor
{
template
<
class
...
Ts
>
string
operator
()(
const
Ts
&
...
xs
)
{
return
deep_to_string
(
std
::
forward_as_tuple
(
xs
...));
}
};
}
// namespace <anonymous>
CAF_TEST
(
n_ary_visit
)
{
variant
<
int
,
string
>
a
{
42
};
variant
<
string
,
atom_value
>
b
{
atom
(
"foo"
)};
variant
<
float
,
int
,
string
>
c
{
string
{
"bar"
}};
variant
<
int
,
string
,
double
>
d
{
123
};
test_visitor
f
;
CAF_CHECK_EQUAL
(
visit
(
f
,
a
,
b
),
"(42, 'foo')"
);
CAF_CHECK_EQUAL
(
visit
(
f
,
a
,
b
,
c
),
"(42, 'foo',
\"
bar
\"
)"
);
CAF_CHECK_EQUAL
(
visit
(
f
,
a
,
b
,
c
,
d
),
"(42, 'foo',
\"
bar
\"
, 123)"
);
}
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