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
3890119e
Commit
3890119e
authored
Feb 09, 2018
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement n-ary visit
parent
f9f874d5
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
83 additions
and
24 deletions
+83
-24
libcaf_core/caf/variant.hpp
libcaf_core/caf/variant.hpp
+61
-24
libcaf_core/test/variant.cpp
libcaf_core/test/variant.cpp
+22
-0
No files found.
libcaf_core/caf/variant.hpp
View file @
3890119e
...
@@ -22,6 +22,7 @@
...
@@ -22,6 +22,7 @@
#include <type_traits>
#include <type_traits>
#include "caf/config.hpp"
#include "caf/config.hpp"
#include "caf/fwd.hpp"
#include "caf/static_visitor.hpp"
#include "caf/static_visitor.hpp"
#include "caf/meta/omittable.hpp"
#include "caf/meta/omittable.hpp"
...
@@ -32,7 +33,15 @@
...
@@ -32,7 +33,15 @@
#define CAF_VARIANT_CASE(n) \
#define CAF_VARIANT_CASE(n) \
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) \
#define CAF_VARIANT_ASSIGN_CASE(n) \
case n: { \
case n: { \
...
@@ -110,6 +119,21 @@ struct is_same_ish
...
@@ -110,6 +119,21 @@ struct is_same_ish
is_equal_int_type
<
T
,
U
>
is_equal_int_type
<
T
,
U
>
>::
type
{
};
>::
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...`.
/// A variant represents always a valid value of one of the types `Ts...`.
template
<
class
...
Ts
>
template
<
class
...
Ts
>
class
variant
{
class
variant
{
...
@@ -206,20 +230,20 @@ public:
...
@@ -206,20 +230,20 @@ public:
return
data_
.
get
(
token
);
return
data_
.
get
(
token
);
}
}
template
<
class
Result
,
class
Visitor
>
template
<
class
Result
,
class
Visitor
,
class
...
Variants
>
Result
apply
(
Visitor
&&
visitor
)
const
{
Result
apply
(
Visitor
&&
visitor
,
Variants
&&
...
xs
)
const
{
return
apply_impl
<
Result
>
(
*
this
,
std
::
forward
<
Visitor
>
(
visitor
),
return
apply_impl
<
Result
>
(
*
this
,
std
::
forward
<
Visitor
>
(
visitor
),
variant_marker
);
std
::
forward
<
Variants
>
(
xs
)...,
variant_marker
);
}
}
template
<
class
Result
,
class
Visitor
>
template
<
class
Result
,
class
Visitor
,
class
...
Variants
>
Result
apply
(
Visitor
&&
visitor
)
{
Result
apply
(
Visitor
&&
visitor
,
Variants
&&
...
xs
)
{
return
apply_impl
<
Result
>
(
*
this
,
std
::
forward
<
Visitor
>
(
visitor
),
return
apply_impl
<
Result
>
(
*
this
,
std
::
forward
<
Visitor
>
(
visitor
),
variant_marker
);
std
::
forward
<
Variants
>
(
xs
)...,
variant_marker
);
}
}
template
<
class
Result
,
class
Self
,
class
Visitor
>
template
<
class
Result
,
class
Self
,
class
Visitor
,
class
...
Us
>
static
Result
apply_impl
(
Self
&
x
,
Visitor
&&
f
,
variant_marker_t
)
{
static
Result
apply_impl
(
Self
&
x
,
Visitor
&&
f
,
variant_marker_t
,
Us
&&
...
xs
)
{
switch
(
x
.
type_
)
{
switch
(
x
.
type_
)
{
default:
CAF_RAISE_ERROR
(
"invalid type found"
);
default:
CAF_RAISE_ERROR
(
"invalid type found"
);
CAF_VARIANT_CASE
(
0
);
CAF_VARIANT_CASE
(
0
);
...
@@ -244,6 +268,34 @@ public:
...
@@ -244,6 +268,34 @@ public:
CAF_VARIANT_CASE
(
19
);
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
/// @endcond
private:
private:
...
@@ -304,21 +356,6 @@ private:
...
@@ -304,21 +356,6 @@ private:
detail
::
variant_data
<
typename
lift_void
<
Ts
>::
type
...
>
data_
;
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
{};
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
{};
/// @relates variant
/// @relates variant
template
<
class
T
,
class
...
Us
>
template
<
class
T
,
class
...
Us
>
T
&
get
(
variant
<
Us
...
>&
value
)
{
T
&
get
(
variant
<
Us
...
>&
value
)
{
...
...
libcaf_core/test/variant.cpp
View file @
3890119e
...
@@ -127,3 +127,25 @@ CAF_TEST(copying_moving_roundtrips) {
...
@@ -127,3 +127,25 @@ CAF_TEST(copying_moving_roundtrips) {
macro_repeat20
(
v20_test
);
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