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
844ad3db
Commit
844ad3db
authored
Sep 08, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix handling of implicitly convertible types
parent
3e5d8071
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
135 additions
and
58 deletions
+135
-58
libcaf_core/caf/detail/stringification_inspector.hpp
libcaf_core/caf/detail/stringification_inspector.hpp
+16
-17
libcaf_core/caf/detail/type_traits.hpp
libcaf_core/caf/detail/type_traits.hpp
+58
-6
libcaf_core/caf/inspector_access.hpp
libcaf_core/caf/inspector_access.hpp
+10
-0
libcaf_core/caf/inspector_access_type.hpp
libcaf_core/caf/inspector_access_type.hpp
+45
-34
libcaf_core/src/config_value.cpp
libcaf_core/src/config_value.cpp
+5
-0
libcaf_core/src/detail/stringification_inspector.cpp
libcaf_core/src/detail/stringification_inspector.cpp
+1
-1
No files found.
libcaf_core/caf/detail/stringification_inspector.hpp
View file @
844ad3db
...
@@ -127,13 +127,16 @@ public:
...
@@ -127,13 +127,16 @@ public:
bool
value
(
const
std
::
vector
<
bool
>&
xs
);
bool
value
(
const
std
::
vector
<
bool
>&
xs
);
// -- builtin inspection to pick up to_string or provide nicer formatting ----
template
<
class
Rep
,
class
Period
>
template
<
class
Rep
,
class
Period
>
bool
value
(
const
std
::
chrono
::
duration
<
Rep
,
Period
>
x
)
{
bool
builtin_inspect
(
const
std
::
chrono
::
duration
<
Rep
,
Period
>
x
)
{
return
value
(
std
::
chrono
::
duration_cast
<
timespan
>
(
x
));
return
value
(
std
::
chrono
::
duration_cast
<
timespan
>
(
x
));
}
}
template
<
class
T
>
template
<
class
T
>
std
::
enable_if_t
<
detail
::
is_map_like_v
<
T
>
,
bool
>
value
(
const
T
&
xs
)
{
std
::
enable_if_t
<
detail
::
is_map_like_v
<
T
>
,
bool
>
builtin_inspect
(
const
T
&
xs
)
{
sep
();
sep
();
auto
i
=
xs
.
begin
();
auto
i
=
xs
.
begin
();
auto
last
=
xs
.
end
();
auto
last
=
xs
.
end
();
...
@@ -159,7 +162,7 @@ public:
...
@@ -159,7 +162,7 @@ public:
std
::
enable_if_t
<
has_to_string
<
T
>::
value
std
::
enable_if_t
<
has_to_string
<
T
>::
value
&&
!
std
::
is_convertible
<
T
,
string_view
>::
value
,
&&
!
std
::
is_convertible
<
T
,
string_view
>::
value
,
bool
>
bool
>
value
(
const
T
&
x
)
{
builtin_inspect
(
const
T
&
x
)
{
auto
str
=
to_string
(
x
);
auto
str
=
to_string
(
x
);
if
constexpr
(
std
::
is_convertible
<
decltype
(
str
),
const
char
*>::
value
)
{
if
constexpr
(
std
::
is_convertible
<
decltype
(
str
),
const
char
*>::
value
)
{
const
char
*
cstr
=
str
;
const
char
*
cstr
=
str
;
...
@@ -171,10 +174,10 @@ public:
...
@@ -171,10 +174,10 @@ public:
return
true
;
return
true
;
}
}
bool
value
(
const
char
*
x
);
bool
builtin_inspect
(
const
char
*
x
);
template
<
class
T
>
template
<
class
T
>
bool
value
(
const
T
*
x
)
{
bool
builtin_inspect
(
const
T
*
x
)
{
sep
();
sep
();
if
(
!
x
)
{
if
(
!
x
)
{
result_
+=
"null"
;
result_
+=
"null"
;
...
@@ -186,7 +189,7 @@ public:
...
@@ -186,7 +189,7 @@ public:
}
}
template
<
class
T
>
template
<
class
T
>
bool
value
(
const
optional
<
T
>&
x
)
{
bool
builtin_inspect
(
const
optional
<
T
>&
x
)
{
sep
();
sep
();
if
(
!
x
)
{
if
(
!
x
)
{
result_
+=
"null"
;
result_
+=
"null"
;
...
@@ -197,17 +200,7 @@ public:
...
@@ -197,17 +200,7 @@ public:
return
true
;
return
true
;
}
}
template
<
class
T
>
// -- fallbacks --------------------------------------------------------------
void
append
(
T
&&
str
)
{
sep
();
result_
.
insert
(
result_
.
end
(),
str
.
begin
(),
str
.
end
());
}
template
<
class
...
Ts
>
bool
opaque_value
(
variant
<
Ts
...
>&
val
)
{
auto
f
=
[
this
](
auto
&
x
)
{
return
save_value
(
*
this
,
x
);
};
return
visit
(
f
,
val
);
}
template
<
class
T
>
template
<
class
T
>
bool
opaque_value
(
T
&
val
)
{
bool
opaque_value
(
T
&
val
)
{
...
@@ -221,6 +214,12 @@ public:
...
@@ -221,6 +214,12 @@ public:
}
}
private:
private:
template
<
class
T
>
void
append
(
T
&&
str
)
{
sep
();
result_
.
insert
(
result_
.
end
(),
str
.
begin
(),
str
.
end
());
}
template
<
class
Iterator
,
class
Sentinel
>
template
<
class
Iterator
,
class
Sentinel
>
void
print_list
(
Iterator
first
,
Sentinel
sentinel
)
{
void
print_list
(
Iterator
first
,
Sentinel
sentinel
)
{
sep
();
sep
();
...
...
libcaf_core/caf/detail/type_traits.hpp
View file @
844ad3db
...
@@ -831,15 +831,16 @@ public:
...
@@ -831,15 +831,16 @@ public:
static
constexpr
bool
value
=
result_type
::
value
;
static
constexpr
bool
value
=
result_type
::
value
;
};
};
/// Checks whether the inspector has a `
value
` overload for `T`.
/// Checks whether the inspector has a `
builtin_inspect
` overload for `T`.
template
<
class
Inspector
,
class
T
>
template
<
class
Inspector
,
class
T
>
class
is_trivially_inspectable
{
class
has_builtin_inspect
{
private:
private:
template
<
class
U
>
template
<
class
I
,
class
U
>
static
auto
sfinae
(
I
nspector
&
f
,
U
&
x
)
static
auto
sfinae
(
I
&
f
,
U
&
x
)
->
decltype
(
f
.
value
(
x
),
std
::
true_type
{});
->
decltype
(
f
.
builtin_inspect
(
x
),
std
::
true_type
{});
static
std
::
false_type
sfinae
(
Inspector
&
,
...);
template
<
class
I
>
static
std
::
false_type
sfinae
(
I
&
,
...);
using
sfinae_result
using
sfinae_result
=
decltype
(
sfinae
(
std
::
declval
<
Inspector
&>
(),
std
::
declval
<
T
&>
()));
=
decltype
(
sfinae
(
std
::
declval
<
Inspector
&>
(),
std
::
declval
<
T
&>
()));
...
@@ -848,6 +849,57 @@ public:
...
@@ -848,6 +849,57 @@ public:
static
constexpr
bool
value
=
sfinae_result
::
value
;
static
constexpr
bool
value
=
sfinae_result
::
value
;
};
};
/// Checks whether inspectors are required to provide a `value` overload for T.
template
<
bool
IsLoading
,
class
T
>
struct
is_trivial_inspector_value
;
template
<
class
T
>
struct
is_trivial_inspector_value
<
true
,
T
>
{
static
constexpr
bool
value
=
false
;
};
template
<
class
T
>
struct
is_trivial_inspector_value
<
false
,
T
>
{
static
constexpr
bool
value
=
std
::
is_convertible
<
T
,
string_view
>::
value
;
};
#define CAF_ADD_TRIVIAL_LOAD_INSPECTOR_VALUE(type) \
template <> \
struct is_trivial_inspector_value<true, type> { \
static constexpr bool value = true; \
};
#define CAF_ADD_TRIVIAL_SAVE_INSPECTOR_VALUE(type) \
template <> \
struct is_trivial_inspector_value<false, type> { \
static constexpr bool value = true; \
};
#define CAF_ADD_TRIVIAL_INSPECTOR_VALUE(type) \
CAF_ADD_TRIVIAL_LOAD_INSPECTOR_VALUE(type) \
CAF_ADD_TRIVIAL_SAVE_INSPECTOR_VALUE(type)
CAF_ADD_TRIVIAL_INSPECTOR_VALUE
(
bool
);
CAF_ADD_TRIVIAL_INSPECTOR_VALUE
(
float
);
CAF_ADD_TRIVIAL_INSPECTOR_VALUE
(
double
);
CAF_ADD_TRIVIAL_INSPECTOR_VALUE
(
long
double
);
CAF_ADD_TRIVIAL_INSPECTOR_VALUE
(
std
::
u16string
);
CAF_ADD_TRIVIAL_INSPECTOR_VALUE
(
std
::
u32string
);
CAF_ADD_TRIVIAL_INSPECTOR_VALUE
(
std
::
vector
<
bool
>
);
CAF_ADD_TRIVIAL_INSPECTOR_VALUE
(
span
<
byte
>
);
CAF_ADD_TRIVIAL_SAVE_INSPECTOR_VALUE
(
span
<
const
byte
>
);
CAF_ADD_TRIVIAL_LOAD_INSPECTOR_VALUE
(
std
::
string
);
#undef CAF_ADD_TRIVIAL_INSPECTOR_VALUE
#undef CAF_ADD_TRIVIAL_SAVE_INSPECTOR_VALUE
#undef CAF_ADD_TRIVIAL_LOAD_INSPECTOR_VALUE
template
<
bool
IsLoading
,
class
T
>
constexpr
bool
is_trivial_inspector_value_v
=
is_trivial_inspector_value
<
IsLoading
,
T
>::
value
;
/// Checks whether the inspector has an `opaque_value` overload for `T`.
/// Checks whether the inspector has an `opaque_value` overload for `T`.
template
<
class
Inspector
,
class
T
>
template
<
class
Inspector
,
class
T
>
class
accepts_opaque_value
{
class
accepts_opaque_value
{
...
...
libcaf_core/caf/inspector_access.hpp
View file @
844ad3db
...
@@ -102,6 +102,11 @@ bool load_value(Inspector& f, T& x, inspector_access_type::integral) {
...
@@ -102,6 +102,11 @@ bool load_value(Inspector& f, T& x, inspector_access_type::integral) {
template
<
class
Inspector
,
class
T
>
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
builtin
)
{
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
builtin
)
{
return
f
.
builtin_inspect
(
x
);
}
template
<
class
Inspector
,
class
T
>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
trivial
)
{
return
f
.
value
(
x
);
return
f
.
value
(
x
);
}
}
...
@@ -280,6 +285,11 @@ bool save_value(Inspector& f, T& x, inspector_access_type::integral) {
...
@@ -280,6 +285,11 @@ bool save_value(Inspector& f, T& x, inspector_access_type::integral) {
template
<
class
Inspector
,
class
T
>
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
builtin
)
{
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
builtin
)
{
return
f
.
builtin_inspect
(
x
);
}
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
trivial
)
{
return
f
.
value
(
x
);
return
f
.
value
(
x
);
}
}
...
...
libcaf_core/caf/inspector_access_type.hpp
View file @
844ad3db
...
@@ -18,11 +18,15 @@
...
@@ -18,11 +18,15 @@
#pragma once
#pragma once
#include <string>
#include <type_traits>
#include <type_traits>
#include <vector>
#include "caf/detail/is_complete.hpp"
#include "caf/detail/is_complete.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include "caf/fwd.hpp"
#include "caf/span.hpp"
#include "caf/string_view.hpp"
namespace
caf
{
namespace
caf
{
...
@@ -40,9 +44,12 @@ struct inspector_access_type {
...
@@ -40,9 +44,12 @@ struct inspector_access_type {
/// Flags builtin integral types.
/// Flags builtin integral types.
struct
integral
{};
struct
integral
{};
/// Flags types with builtin support via `
.value()
`.
/// Flags types with builtin support via `
Inspector::builtin_inspect
`.
struct
builtin
{};
struct
builtin
{};
/// Flags types with builtin support via `Inspector::value`.
struct
trivial
{};
/// Flags `enum` types.
/// Flags `enum` types.
struct
enumeration
{};
struct
enumeration
{};
...
@@ -74,69 +81,73 @@ struct inspector_access_type {
...
@@ -74,69 +81,73 @@ struct inspector_access_type {
/// @relates inspector_access_type
/// @relates inspector_access_type
template
<
class
Inspector
,
class
T
>
template
<
class
Inspector
,
class
T
>
constexpr
auto
inspect_object_access_type
()
{
constexpr
auto
inspect_object_access_type
()
{
// Order: inspector_access > inspect > defaults.
using
namespace
detail
;
using
namespace
detail
;
if
constexpr
(
is_allowed_unsafe_message_type_v
<
T
>
)
{
// Order: unsafe (error) > C Array > builtin_inspect > inspector_access >
// inspect > trivial > defaults.
if
constexpr
(
is_allowed_unsafe_message_type_v
<
T
>
)
return
inspector_access_type
::
unsafe
{};
return
inspector_access_type
::
unsafe
{};
}
else
if
constexpr
(
detail
::
is_complete
<
inspector_access
<
T
>>
)
{
else
if
constexpr
(
std
::
is_array
<
T
>::
value
)
return
inspector_access_type
::
array
{};
else
if
constexpr
(
has_builtin_inspect
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
builtin
{};
else
if
constexpr
(
detail
::
is_complete
<
inspector_access
<
T
>>
)
return
inspector_access_type
::
specialization
{};
return
inspector_access_type
::
specialization
{};
}
else
if
constexpr
(
has_inspect_overload
<
Inspector
,
T
>::
value
)
{
else
if
constexpr
(
has_inspect_overload
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
inspect
{};
return
inspector_access_type
::
inspect
{};
}
else
if
constexpr
(
std
::
is_integral
<
T
>::
value
else
if
constexpr
(
is_trivial_inspector_value_v
<
Inspector
::
is_loading
,
T
>
)
&&
!
std
::
is_same
<
T
,
bool
>::
value
)
{
return
inspector_access_type
::
trivial
{};
else
if
constexpr
(
std
::
is_integral
<
T
>::
value
)
return
inspector_access_type
::
integral
{};
return
inspector_access_type
::
integral
{};
}
else
if
constexpr
(
std
::
is_array
<
T
>::
value
)
{
else
if
constexpr
(
std
::
is_enum
<
T
>::
value
)
return
inspector_access_type
::
array
{};
}
else
if
constexpr
(
std
::
is_enum
<
T
>::
value
)
{
return
inspector_access_type
::
enumeration
{};
return
inspector_access_type
::
enumeration
{};
}
else
if
constexpr
(
std
::
is_empty
<
T
>::
value
)
{
else
if
constexpr
(
std
::
is_empty
<
T
>::
value
)
return
inspector_access_type
::
empty
{};
return
inspector_access_type
::
empty
{};
}
else
if
constexpr
(
is_stl_tuple_type_v
<
T
>
)
{
else
if
constexpr
(
is_stl_tuple_type_v
<
T
>
)
return
inspector_access_type
::
tuple
{};
return
inspector_access_type
::
tuple
{};
}
else
if
constexpr
(
is_map_like_v
<
T
>
)
{
else
if
constexpr
(
is_map_like_v
<
T
>
)
return
inspector_access_type
::
map
{};
return
inspector_access_type
::
map
{};
}
else
if
constexpr
(
is_list_like_v
<
T
>
)
{
else
if
constexpr
(
is_list_like_v
<
T
>
)
return
inspector_access_type
::
list
{};
return
inspector_access_type
::
list
{};
}
else
{
else
return
inspector_access_type
::
none
{};
return
inspector_access_type
::
none
{};
}
}
}
/// @relates inspector_access_type
/// @relates inspector_access_type
template
<
class
Inspector
,
class
T
>
template
<
class
Inspector
,
class
T
>
constexpr
auto
inspect_value_access_type
()
{
constexpr
auto
inspect_value_access_type
()
{
// Order: .value > inspector_access > inspect_value > inspect > defaults.
// Order: unsafe (error) > C Array > builtin_inspect > inspector_access >
// However, C-arrays convert easily into something that .value overloads might
// inspect_value > inspect > defaults.
// pick up. Hence, we single them out above all else.
// This is the same as in inspect_object_access_type, except that we pick up
// inspect_value overloads.
using
namespace
detail
;
using
namespace
detail
;
if
constexpr
(
is_allowed_unsafe_message_type_v
<
T
>
)
{
if
constexpr
(
is_allowed_unsafe_message_type_v
<
T
>
)
return
inspector_access_type
::
unsafe
{};
return
inspector_access_type
::
unsafe
{};
}
else
if
constexpr
(
std
::
is_array
<
T
>::
value
)
{
else
if
constexpr
(
std
::
is_array
<
T
>::
value
)
return
inspector_access_type
::
array
{};
return
inspector_access_type
::
array
{};
}
else
if
constexpr
(
is_trivially_inspectable
<
Inspector
,
T
>::
value
)
{
else
if
constexpr
(
has_builtin_inspect
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
builtin
{};
return
inspector_access_type
::
builtin
{};
}
else
if
constexpr
(
detail
::
is_complete
<
inspector_access
<
T
>>
)
{
else
if
constexpr
(
detail
::
is_complete
<
inspector_access
<
T
>>
)
return
inspector_access_type
::
specialization
{};
return
inspector_access_type
::
specialization
{};
}
else
if
constexpr
(
has_inspect_value_overload
<
Inspector
,
T
>::
value
)
{
else
if
constexpr
(
has_inspect_value_overload
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
inspect_value
{};
return
inspector_access_type
::
inspect_value
{};
}
else
if
constexpr
(
has_inspect_overload
<
Inspector
,
T
>::
value
)
{
else
if
constexpr
(
has_inspect_overload
<
Inspector
,
T
>::
value
)
return
inspector_access_type
::
inspect
{};
return
inspector_access_type
::
inspect
{};
}
else
if
constexpr
(
std
::
is_integral
<
T
>::
value
else
if
constexpr
(
is_trivial_inspector_value_v
<
Inspector
::
is_loading
,
T
>
)
&&
!
std
::
is_same
<
T
,
bool
>::
value
)
{
return
inspector_access_type
::
trivial
{};
else
if
constexpr
(
std
::
is_integral
<
T
>::
value
)
return
inspector_access_type
::
integral
{};
return
inspector_access_type
::
integral
{};
}
else
if
constexpr
(
std
::
is_enum
<
T
>::
value
)
{
else
if
constexpr
(
std
::
is_enum
<
T
>::
value
)
return
inspector_access_type
::
enumeration
{};
return
inspector_access_type
::
enumeration
{};
}
else
if
constexpr
(
std
::
is_empty
<
T
>::
value
)
{
else
if
constexpr
(
std
::
is_empty
<
T
>::
value
)
return
inspector_access_type
::
empty
{};
return
inspector_access_type
::
empty
{};
}
else
if
constexpr
(
is_stl_tuple_type_v
<
T
>
)
{
else
if
constexpr
(
is_stl_tuple_type_v
<
T
>
)
return
inspector_access_type
::
tuple
{};
return
inspector_access_type
::
tuple
{};
}
else
if
constexpr
(
is_map_like_v
<
T
>
)
{
else
if
constexpr
(
is_map_like_v
<
T
>
)
return
inspector_access_type
::
map
{};
return
inspector_access_type
::
map
{};
}
else
if
constexpr
(
is_list_like_v
<
T
>
)
{
else
if
constexpr
(
is_list_like_v
<
T
>
)
return
inspector_access_type
::
list
{};
return
inspector_access_type
::
list
{};
}
else
{
else
return
inspector_access_type
::
none
{};
return
inspector_access_type
::
none
{};
}
}
}
}
// namespace caf
}
// namespace caf
libcaf_core/src/config_value.cpp
View file @
844ad3db
...
@@ -150,6 +150,11 @@ struct to_string_visitor {
...
@@ -150,6 +150,11 @@ struct to_string_visitor {
f
.
value
(
x
);
f
.
value
(
x
);
}
}
void
operator
()(
const
uri
&
x
)
{
auto
x_str
=
x
.
str
();
str
.
insert
(
str
.
end
(),
x_str
.
begin
(),
x_str
.
end
());
}
void
operator
()(
const
config_value
::
list
&
xs
)
{
void
operator
()(
const
config_value
::
list
&
xs
)
{
if
(
xs
.
empty
())
{
if
(
xs
.
empty
())
{
str
+=
"[]"
;
str
+=
"[]"
;
...
...
libcaf_core/src/detail/stringification_inspector.cpp
View file @
844ad3db
...
@@ -228,7 +228,7 @@ bool stringification_inspector::value(const std::vector<bool>& xs) {
...
@@ -228,7 +228,7 @@ bool stringification_inspector::value(const std::vector<bool>& xs) {
return
end_sequence
();
return
end_sequence
();
}
}
bool
stringification_inspector
::
value
(
const
char
*
x
)
{
bool
stringification_inspector
::
builtin_inspect
(
const
char
*
x
)
{
return
value
(
string_view
{
x
,
strlen
(
x
)});
return
value
(
string_view
{
x
,
strlen
(
x
)});
}
}
...
...
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