aboutsummaryrefslogtreecommitdiff
path: root/src/univalue
diff options
context:
space:
mode:
authorfanquake <fanquake@gmail.com>2022-07-25 15:01:16 +0100
committerfanquake <fanquake@gmail.com>2022-07-25 15:12:41 +0100
commit73a0d6d0d4c4a75d078466bd9a80b6b4101256d1 (patch)
treebc1dea8c21388e2622ac83686c7d488eb622cbd6 /src/univalue
parentc991132b0437b737502ae1f18480e00f84430b72 (diff)
parentfa23c197509f692a815193acc1b50bad2fcbedfe (diff)
downloadbitcoin-73a0d6d0d4c4a75d078466bd9a80b6b4101256d1.tar.xz
Merge bitcoin/bitcoin#25611: univalue: Avoid brittle, narrowing and verbose integral type confusions
fa23c197509f692a815193acc1b50bad2fcbedfe univalue: Avoid narrowing and verbose int constructors (MacroFake) fa3a9a1e8d9b6dffda772e97c279f3c0af6813f9 rpc: Select int-UniValue constructor for enum value in upgradewallet RPC (MacroFake) Pull request description: As UniValue provides several constructors for integral types, the compiler is unable to select one if the passed type does not exactly match. This is unintuitive for developers and forces them to write verbose and brittle code. (Refer to `-Wnarrowing` compiler warning) For example, there are many places where an unsigned int is cast to a signed int. While the cast is safe in practice, it is still needlessly verbose and confusing as the value can never be negative. In fact it might even be unsafe if the unsigned value is large enough to map to a negative signed one. Fix this issue and other (minor) type issues. ACKs for top commit: aureleoules: ACK fa23c197509f692a815193acc1b50bad2fcbedfe. Tree-SHA512: 7d99b5b90c7d8eed2e3448167255a59e817dd6b8fcfc1b17c69ddefd0db33d1bf4344fbcd8b7f8685b58182c0f572ab9ffa99467afa666ac21843df7ea645033
Diffstat (limited to 'src/univalue')
-rw-r--r--src/univalue/include/univalue.h40
1 files changed, 19 insertions, 21 deletions
diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h
index dff544f96f..230a5fd096 100644
--- a/src/univalue/include/univalue.h
+++ b/src/univalue/include/univalue.h
@@ -24,27 +24,25 @@ public:
typ = initialType;
val = initialStr;
}
- UniValue(uint64_t val_) {
- setInt(val_);
- }
- UniValue(int64_t val_) {
- setInt(val_);
- }
- UniValue(bool val_) {
- setBool(val_);
- }
- UniValue(int val_) {
- setInt(val_);
- }
- UniValue(double val_) {
- setFloat(val_);
- }
- UniValue(const std::string& val_) {
- setStr(val_);
- }
- UniValue(const char *val_) {
- std::string s(val_);
- setStr(s);
+ template <typename Ref, typename T = std::remove_cv_t<std::remove_reference_t<Ref>>,
+ std::enable_if_t<std::is_floating_point_v<T> || // setFloat
+ std::is_same_v<bool, T> || // setBool
+ std::is_signed_v<T> || std::is_unsigned_v<T> || // setInt
+ std::is_constructible_v<std::string, T>, // setStr
+ bool> = true>
+ UniValue(Ref&& val)
+ {
+ if constexpr (std::is_floating_point_v<T>) {
+ setFloat(val);
+ } else if constexpr (std::is_same_v<bool, T>) {
+ setBool(val);
+ } else if constexpr (std::is_signed_v<T>) {
+ setInt(int64_t{val});
+ } else if constexpr (std::is_unsigned_v<T>) {
+ setInt(uint64_t{val});
+ } else {
+ setStr(std::string{std::forward<Ref>(val)});
+ }
}
void clear();