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
ddb7719e
Commit
ddb7719e
authored
Aug 27, 2019
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow treating config_value as a tuple
parent
d771808b
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
105 additions
and
1 deletion
+105
-1
libcaf_core/caf/config_value.hpp
libcaf_core/caf/config_value.hpp
+73
-0
libcaf_core/test/config_value.cpp
libcaf_core/test/config_value.cpp
+32
-1
No files found.
libcaf_core/caf/config_value.hpp
View file @
ddb7719e
...
@@ -24,11 +24,13 @@
...
@@ -24,11 +24,13 @@
#include <iterator>
#include <iterator>
#include <map>
#include <map>
#include <string>
#include <string>
#include <tuple>
#include <type_traits>
#include <type_traits>
#include <vector>
#include <vector>
#include "caf/atom.hpp"
#include "caf/atom.hpp"
#include "caf/detail/bounds_checker.hpp"
#include "caf/detail/bounds_checker.hpp"
#include "caf/detail/move_if_not_ptr.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/dictionary.hpp"
#include "caf/dictionary.hpp"
#include "caf/fwd.hpp"
#include "caf/fwd.hpp"
...
@@ -387,6 +389,77 @@ struct config_value_access<std::vector<T>> {
...
@@ -387,6 +389,77 @@ struct config_value_access<std::vector<T>> {
}
}
};
};
/// Implements automagic unboxing of `std::tuple<Ts...>` from a heterogeneous
///`config_value::list`.
/// @relates config_value
template
<
class
...
Ts
>
struct
config_value_access
<
std
::
tuple
<
Ts
...
>>
{
using
tuple_type
=
std
::
tuple
<
Ts
...
>
;
static
constexpr
bool
specialized
=
true
;
static
bool
is
(
const
config_value
&
x
)
{
if
(
auto
lst
=
caf
::
get_if
<
config_value
::
list
>
(
&
x
))
{
if
(
lst
->
size
()
!=
sizeof
...(
Ts
))
return
false
;
return
rec_is
(
*
lst
,
detail
::
int_token
<
0
>
(),
detail
::
type_list
<
Ts
...
>
());
}
return
false
;
}
static
optional
<
tuple_type
>
get_if
(
const
config_value
*
x
)
{
if
(
auto
lst
=
caf
::
get_if
<
config_value
::
list
>
(
x
))
{
if
(
lst
->
size
()
!=
sizeof
...(
Ts
))
return
none
;
tuple_type
result
;
if
(
rec_get
(
*
lst
,
result
,
detail
::
int_token
<
0
>
(),
detail
::
type_list
<
Ts
...
>
()))
return
result
;
}
return
none
;
}
static
tuple_type
get
(
const
config_value
&
x
)
{
if
(
auto
result
=
get_if
(
&
x
))
return
std
::
move
(
*
result
);
CAF_RAISE_ERROR
(
"invalid type found"
);
}
private:
template
<
int
Pos
>
static
bool
rec_is
(
const
config_value
::
list
&
,
detail
::
int_token
<
Pos
>
,
detail
::
type_list
<>
)
{
// End of recursion.
return
true
;
}
template
<
int
Pos
,
class
U
,
class
...
Us
>
static
bool
rec_is
(
const
config_value
::
list
&
xs
,
detail
::
int_token
<
Pos
>
,
detail
::
type_list
<
U
,
Us
...
>
)
{
if
(
!
holds_alternative
<
U
>
(
xs
[
Pos
]))
return
false
;
return
rec_is
(
xs
,
detail
::
int_token
<
Pos
+
1
>
(),
detail
::
type_list
<
Us
...
>
());
}
template
<
int
Pos
>
static
bool
rec_get
(
const
config_value
::
list
&
,
tuple_type
&
,
detail
::
int_token
<
Pos
>
,
detail
::
type_list
<>
)
{
// End of recursion.
return
true
;
}
template
<
int
Pos
,
class
U
,
class
...
Us
>
static
bool
rec_get
(
const
config_value
::
list
&
xs
,
tuple_type
&
result
,
detail
::
int_token
<
Pos
>
,
detail
::
type_list
<
U
,
Us
...
>
)
{
if
(
auto
value
=
caf
::
get_if
<
U
>
(
&
xs
[
Pos
]))
{
std
::
get
<
Pos
>
(
result
)
=
detail
::
move_if_not_ptr
(
value
);
return
rec_get
(
xs
,
result
,
detail
::
int_token
<
Pos
+
1
>
(),
detail
::
type_list
<
Us
...
>
());
}
return
false
;
}
};
/// Implements automagic unboxing of `dictionary<V>` from a homogeneous
/// Implements automagic unboxing of `dictionary<V>` from a homogeneous
/// `config_value::dictionary`.
/// `config_value::dictionary`.
/// @relates config_value
/// @relates config_value
...
...
libcaf_core/test/config_value.cpp
View file @
ddb7719e
...
@@ -129,7 +129,7 @@ CAF_TEST(timespan) {
...
@@ -129,7 +129,7 @@ CAF_TEST(timespan) {
CAF_CHECK_NOT_EQUAL
(
get_if
<
timespan
>
(
&
x
),
nullptr
);
CAF_CHECK_NOT_EQUAL
(
get_if
<
timespan
>
(
&
x
),
nullptr
);
}
}
CAF_TEST
(
list
)
{
CAF_TEST
(
homogeneous
list
)
{
using
integer_list
=
std
::
vector
<
int64_t
>
;
using
integer_list
=
std
::
vector
<
int64_t
>
;
auto
xs
=
make_config_value_list
(
1
,
2
,
3
);
auto
xs
=
make_config_value_list
(
1
,
2
,
3
);
auto
ys
=
config_value
{
integer_list
{
1
,
2
,
3
}};
auto
ys
=
config_value
{
integer_list
{
1
,
2
,
3
}};
...
@@ -141,6 +141,16 @@ CAF_TEST(list) {
...
@@ -141,6 +141,16 @@ CAF_TEST(list) {
CAF_CHECK_EQUAL
(
get
<
integer_list
>
(
xs
),
integer_list
({
1
,
2
,
3
}));
CAF_CHECK_EQUAL
(
get
<
integer_list
>
(
xs
),
integer_list
({
1
,
2
,
3
}));
}
}
CAF_TEST
(
heterogeneous
list
)
{
auto
xs_value
=
make_config_value_list
(
1
,
"two"
,
3.0
);
auto
&
xs
=
xs_value
.
as_list
();
CAF_CHECK_EQUAL
(
xs_value
.
type_name
(),
"list"
_s
);
CAF_REQUIRE_EQUAL
(
xs
.
size
(),
3u
);
CAF_CHECK_EQUAL
(
xs
[
0
],
1
);
CAF_CHECK_EQUAL
(
xs
[
1
],
"two"
_s
);
CAF_CHECK_EQUAL
(
xs
[
2
],
3.0
);
}
CAF_TEST
(
convert_to_list
)
{
CAF_TEST
(
convert_to_list
)
{
config_value
x
{
int64_t
{
42
}};
config_value
x
{
int64_t
{
42
}};
CAF_CHECK_EQUAL
(
x
.
type_name
(),
"integer"
_s
);
CAF_CHECK_EQUAL
(
x
.
type_name
(),
"integer"
_s
);
...
@@ -252,3 +262,24 @@ CAF_TEST(unsuccessful parsing) {
...
@@ -252,3 +262,24 @@ CAF_TEST(unsuccessful parsing) {
CAF_CHECK_EQUAL
(
parse
(
"{a=1,"
),
pec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
parse
(
"{a=1,"
),
pec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
parse
(
"{a=1 b=2}"
),
pec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
parse
(
"{a=1 b=2}"
),
pec
::
unexpected_character
);
}
}
CAF_TEST
(
conversion
to
simple
tuple
)
{
using
tuple_type
=
std
::
tuple
<
size_t
,
std
::
string
>
;
config_value
x
{
42
};
x
.
as_list
().
emplace_back
(
"hello world"
);
CAF_REQUIRE
(
holds_alternative
<
tuple_type
>
(
x
));
CAF_REQUIRE_NOT_EQUAL
(
get_if
<
tuple_type
>
(
&
x
),
none
);
CAF_CHECK_EQUAL
(
get
<
tuple_type
>
(
x
),
std
::
make_tuple
(
size_t
{
42
},
"hello world"
_s
));
}
CAF_TEST
(
conversion
to
nested
tuple
)
{
using
inner_tuple_type
=
std
::
tuple
<
int
,
int
>
;
using
tuple_type
=
std
::
tuple
<
size_t
,
inner_tuple_type
>
;
config_value
x
{
42
};
x
.
as_list
().
emplace_back
(
make_config_value_list
(
2
,
40
));
CAF_REQUIRE
(
holds_alternative
<
tuple_type
>
(
x
));
CAF_REQUIRE_NOT_EQUAL
(
get_if
<
tuple_type
>
(
&
x
),
none
);
CAF_CHECK_EQUAL
(
get
<
tuple_type
>
(
x
),
std
::
make_tuple
(
size_t
{
42
},
std
::
make_tuple
(
2
,
40
)));
}
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