From 2aae3f25a7e79d604a6000812c8ff91bf6c159c2 Mon Sep 17 00:00:00 2001 From: Michael Hordijk Date: Sun, 4 Feb 2024 21:22:58 -0700 Subject: [PATCH 1/3] Correctly stream out quantities with a char Rep Quantities that have a `char` `Rep` will have the resulting raw number streamed as a `char`. Given that a Quantity is a number, users would expect that a the value would be streamed as the integral number, not interpreted as a character code. --- au/io.hh | 2 +- au/io_test.cc | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/au/io.hh b/au/io.hh index 29570746..26c8165c 100644 --- a/au/io.hh +++ b/au/io.hh @@ -25,7 +25,7 @@ namespace au { // Streaming output support for Quantity types. template std::ostream &operator<<(std::ostream &out, const Quantity &q) { - out << q.in(U{}) << " " << unit_label(U{}); + out << +q.in(U{}) << " " << unit_label(U{}); return out; } diff --git a/au/io_test.cc b/au/io_test.cc index 00da12ef..d3dfe036 100644 --- a/au/io_test.cc +++ b/au/io_test.cc @@ -61,6 +61,8 @@ TEST(StreamingOutput, PrintsValueAndUnitLabel) { EXPECT_EQ(stream_to_string((feet / milli(second))(1.25)), "1.25 ft / ms"); } +TEST(StreamingOutput, PrintValueRepChar) { EXPECT_EQ(stream_to_string(feet(char{3})), "3 ft"); } + TEST(StreamingOutput, DistinguishesPointFromQuantityByAtSign) { EXPECT_EQ(stream_to_string(celsius_qty(20)), "20 deg C"); EXPECT_EQ(stream_to_string(celsius_pt(20)), "@(20 deg C)"); From 71ed45ee584fc345775ccdd44770b584f4c1d1c7 Mon Sep 17 00:00:00 2001 From: Michael Hordijk Date: Mon, 5 Feb 2024 15:30:16 -0700 Subject: [PATCH 2/3] add comment regarding use of unary `+` operator --- au/io.hh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/au/io.hh b/au/io.hh index 26c8165c..f52464ff 100644 --- a/au/io.hh +++ b/au/io.hh @@ -25,6 +25,11 @@ namespace au { // Streaming output support for Quantity types. template std::ostream &operator<<(std::ostream &out, const Quantity &q) { + // In the case that the Rep is a type that resolves to 'char' (e.g. int8_t), + // the << operator will match the implementation that takes a character + // literal. Using the unary + operator will trigger an integer promotion on + // the operand, which will then match an appropriate << operator that will + // output the integer representation. out << +q.in(U{}) << " " << unit_label(U{}); return out; } From 36895938c2941a221513b7ace03fbebff69347d8 Mon Sep 17 00:00:00 2001 From: Michael Hordijk Date: Mon, 5 Feb 2024 15:30:40 -0700 Subject: [PATCH 3/3] use `int8_t` for unit testing `char` Rep output --- au/io_test.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/au/io_test.cc b/au/io_test.cc index d3dfe036..c434da5a 100644 --- a/au/io_test.cc +++ b/au/io_test.cc @@ -14,6 +14,8 @@ #include "au/io.hh" +#include + #include "au/prefix.hh" #include "au/quantity.hh" #include "gtest/gtest.h" @@ -61,7 +63,13 @@ TEST(StreamingOutput, PrintsValueAndUnitLabel) { EXPECT_EQ(stream_to_string((feet / milli(second))(1.25)), "1.25 ft / ms"); } -TEST(StreamingOutput, PrintValueRepChar) { EXPECT_EQ(stream_to_string(feet(char{3})), "3 ft"); } +TEST(StreamingOutput, PrintValueRepChar) { + // If the Rep resolves to a char, we sill want the number '65' to be output, + // not the character literal that corresponds to 65 ('A'). + static_assert(std::is_same::value, + "Expected 'int8_t' to resolve to 'char'"); + EXPECT_EQ(stream_to_string(feet(int8_t{65})), "65 ft"); +} TEST(StreamingOutput, DistinguishesPointFromQuantityByAtSign) { EXPECT_EQ(stream_to_string(celsius_qty(20)), "20 deg C");