Skip to content

Commit 69dfeb1

Browse files
committed
multiprocess: update common-types.h to use C++20 concepts
Idea came from review comment by ion- bitcoin/bitcoin#30510 (comment)
1 parent 206c6e7 commit 69dfeb1

File tree

1 file changed

+14
-41
lines changed

1 file changed

+14
-41
lines changed

src/ipc/capnp/common-types.h

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define BITCOIN_IPC_CAPNP_COMMON_TYPES_H
77

88
#include <clientversion.h>
9+
#include <serialize.h>
910
#include <streams.h>
1011
#include <univalue.h>
1112

@@ -16,52 +17,23 @@
1617

1718
namespace ipc {
1819
namespace capnp {
19-
//! Use SFINAE to define Serializeable<T> trait which is true if type T has a
20-
//! Serialize(stream) method, false otherwise.
21-
template <typename T>
22-
struct Serializable {
23-
private:
24-
template <typename C>
25-
static std::true_type test(decltype(std::declval<C>().Serialize(std::declval<std::nullptr_t&>()))*);
26-
template <typename>
27-
static std::false_type test(...);
28-
29-
public:
30-
static constexpr bool value = decltype(test<T>(nullptr))::value;
31-
};
32-
33-
//! Use SFINAE to define Unserializeable<T> trait which is true if type T has
34-
//! an Unserialize(stream) method, false otherwise.
35-
template <typename T>
36-
struct Unserializable {
37-
private:
38-
template <typename C>
39-
static std::true_type test(decltype(std::declval<C>().Unserialize(std::declval<std::nullptr_t&>()))*);
40-
template <typename>
41-
static std::false_type test(...);
42-
43-
public:
44-
static constexpr bool value = decltype(test<T>(nullptr))::value;
45-
};
4620
} // namespace capnp
4721
} // namespace ipc
4822

4923
//! Functions to serialize / deserialize common bitcoin types.
5024
namespace mp {
5125
//! Overload multiprocess library's CustomBuildField hook to allow any
5226
//! serializable object to be stored in a capnproto Data field or passed to a
53-
//! canproto interface. Use Priority<1> so this hook has medium priority, and
27+
//! capnproto interface. Use Priority<1> so this hook has medium priority, and
5428
//! higher priority hooks could take precedence over this one.
5529
template <typename LocalType, typename Value, typename Output>
56-
void CustomBuildField(
57-
TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Value&& value, Output&& output,
58-
// Enable if serializeable and if LocalType is not cv or reference
59-
// qualified. If LocalType is cv or reference qualified, it is important to
60-
// fall back to lower-priority Priority<0> implementation of this function
61-
// that strips cv references, to prevent this CustomBuildField overload from
62-
// taking precedence over more narrow overloads for specific LocalTypes.
63-
std::enable_if_t<ipc::capnp::Serializable<LocalType>::value &&
64-
std::is_same_v<LocalType, std::remove_cv_t<std::remove_reference_t<LocalType>>>>* enable = nullptr)
30+
void CustomBuildField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Value&& value, Output&& output)
31+
// Enable if serializeable and if LocalType is not cv or reference qualified. If
32+
// LocalType is cv or reference qualified, it is important to fall back to
33+
// lower-priority Priority<0> implementation of this function that strips cv
34+
// references, to prevent this CustomBuildField overload from taking precedence
35+
// over more narrow overloads for specific LocalTypes.
36+
requires Serializable<LocalType, DataStream> && std::is_same_v<LocalType, std::remove_cv_t<std::remove_reference_t<LocalType>>>
6537
{
6638
DataStream stream;
6739
value.Serialize(stream);
@@ -71,12 +43,11 @@ void CustomBuildField(
7143

7244
//! Overload multiprocess library's CustomReadField hook to allow any object
7345
//! with an Unserialize method to be read from a capnproto Data field or
74-
//! returned from canproto interface. Use Priority<1> so this hook has medium
46+
//! returned from capnproto interface. Use Priority<1> so this hook has medium
7547
//! priority, and higher priority hooks could take precedence over this one.
7648
template <typename LocalType, typename Input, typename ReadDest>
77-
decltype(auto)
78-
CustomReadField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Input&& input, ReadDest&& read_dest,
79-
std::enable_if_t<ipc::capnp::Unserializable<LocalType>::value>* enable = nullptr)
49+
decltype(auto) CustomReadField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context, Input&& input, ReadDest&& read_dest)
50+
requires Unserializable<LocalType, DataStream>
8051
{
8152
return read_dest.update([&](auto& value) {
8253
if (!input.has()) return;
@@ -86,6 +57,8 @@ CustomReadField(TypeList<LocalType>, Priority<1>, InvokeContext& invoke_context,
8657
});
8758
}
8859

60+
//! Overload CustomBuildField and CustomReadField to serialize UniValue
61+
//! parameters and return values as JSON strings.
8962
template <typename Value, typename Output>
9063
void CustomBuildField(TypeList<UniValue>, Priority<1>, InvokeContext& invoke_context, Value&& value, Output&& output)
9164
{

0 commit comments

Comments
 (0)