diff options
author | fanquake <fanquake@gmail.com> | 2024-02-28 21:49:53 +0000 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2024-02-28 22:04:33 +0000 |
commit | bbfddb39983f91b4c5b42958bdf2fe33c144880b (patch) | |
tree | ab5e96a72ce59467eb17d0306492c88a538bd6f0 | |
parent | 7859f4e4b9949912e01bca11aef76d7c1c0452fb (diff) | |
parent | ad7584d8b60119ca3717117a1eb6a16d753c5d74 (diff) | |
download | bitcoin-bbfddb39983f91b4c5b42958bdf2fe33c144880b.tar.xz |
Merge bitcoin/bitcoin#29484: serialization: replace char-is-int8_t autoconf detection with c++20 concept
ad7584d8b60119ca3717117a1eb6a16d753c5d74 serialization: replace char-is-int8_t autoconf detection with c++20 concept (Cory Fields)
Pull request description:
Doesn't depend on #29263, but it's really only relevant after that one's merged.
This removes the only remaining autoconf macro in our serialization code (after #29263), so it can now be used trivially and safely out-of-tree.
~Our code does not currently contain any concepts, but couldn't find any discussion or docs about avoiding them. I guess we'll see if this blows up our c-i.~
Edit: Ignore this. ajtowns pointed out that we're already using a few concepts.
This was introduced in #13580. Please check my logic on this as I'm unable to test on a SmartOS system. Even better would be a confirmation from someone who can build there.
ACKs for top commit:
Empact:
Code review ACK https://github.com/bitcoin/bitcoin/commit/ad7584d8b60119ca3717117a1eb6a16d753c5d74
Tree-SHA512: 1faf65c900700efb1cf3092c607a2230321b393cb2f029fbfb94bc8e50df1dabd7a9e4b91e3b34f0d2f3471aaf18ee7e56d91869db5c5f4bae84da95443e1120
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | src/serialize.h | 20 |
2 files changed, 10 insertions, 18 deletions
diff --git a/configure.ac b/configure.ac index 4a7c02c1e1..078d968b0c 100644 --- a/configure.ac +++ b/configure.ac @@ -1171,14 +1171,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h> [ AC_MSG_RESULT([no])] ) -AC_MSG_CHECKING([for if type char equals int8_t]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdint.h> - #include <type_traits>]], - [[ static_assert(std::is_same<int8_t, char>::value, ""); ]])], - [ AC_MSG_RESULT([yes]); AC_DEFINE([CHAR_EQUALS_INT8], [1], [Define this symbol if type char equals int8_t]) ], - [ AC_MSG_RESULT([no])] -) - AC_MSG_CHECKING([for fdatasync]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>]], [[ fdatasync(0); ]])], diff --git a/src/serialize.h b/src/serialize.h index 7b336ce1af..ab57376a57 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -6,10 +6,6 @@ #ifndef BITCOIN_SERIALIZE_H #define BITCOIN_SERIALIZE_H -#if defined(HAVE_CONFIG_H) -#include <config/bitcoin-config.h> -#endif - #include <attributes.h> #include <compat/assumptions.h> // IWYU pragma: keep #include <compat/endian.h> @@ -17,6 +13,7 @@ #include <span.h> #include <algorithm> +#include <concepts> #include <cstdint> #include <cstring> #include <ios> @@ -263,9 +260,14 @@ const Out& AsBase(const In& x) // i.e. anything that supports .read(Span<std::byte>) and .write(Span<const std::byte>) // // clang-format off -#ifndef CHAR_EQUALS_INT8 -template <typename Stream> void Serialize(Stream&, char) = delete; // char serialization forbidden. Use uint8_t or int8_t -#endif + +// Typically int8_t and char are distinct types, but some systems may define int8_t +// in terms of char. Forbid serialization of char in the typical case, but allow it if +// it's the only way to describe an int8_t. +template<class T> +concept CharNotInt8 = std::same_as<T, char> && !std::same_as<T, int8_t>; + +template <typename Stream, CharNotInt8 V> void Serialize(Stream&, V) = delete; // char serialization forbidden. Use uint8_t or int8_t template <typename Stream> void Serialize(Stream& s, std::byte a) { ser_writedata8(s, uint8_t(a)); } template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); } template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); } @@ -279,9 +281,7 @@ template <typename Stream, BasicByte B, int N> void Serialize(Stream& s, const B template <typename Stream, BasicByte B, std::size_t N> void Serialize(Stream& s, const std::array<B, N>& a) { s.write(MakeByteSpan(a)); } template <typename Stream, BasicByte B> void Serialize(Stream& s, Span<B> span) { s.write(AsBytes(span)); } -#ifndef CHAR_EQUALS_INT8 -template <typename Stream> void Unserialize(Stream&, char) = delete; // char serialization forbidden. Use uint8_t or int8_t -#endif +template <typename Stream, CharNotInt8 V> void Unserialize(Stream&, V) = delete; // char serialization forbidden. Use uint8_t or int8_t template <typename Stream> void Unserialize(Stream& s, std::byte& a) { a = std::byte{ser_readdata8(s)}; } template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); } template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); } |