Skip to content

Commit 9174b0a

Browse files
committed
Changed fmt formatters to make use of overloaded operator insertion.
Fixed an issue in problem 66: binary_search was used in an unordered vector. (cherry picked from commit 8ae6719)
1 parent d78be46 commit 9174b0a

File tree

19 files changed

+264
-846
lines changed

19 files changed

+264
-846
lines changed

include/the_modern_c++_challenge/chapter_02_language_features/array_2d.h

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -424,49 +424,33 @@ namespace tmcppc::data_structures {
424424
return column_widths;
425425
}
426426

427-
private:
428-
friend struct fmt::formatter<array_2d>;
427+
friend std::ostream& operator<<(std::ostream& os, const array_2d<T>& arr) {
428+
if (arr.empty()) {
429+
os << fmt::format("{}", "[]");
430+
} else {
431+
auto column_widths{ get_column_widths(arr) };
432+
433+
for (size_t row{ 0 }; row < arr.height_; ++row) {
434+
os << fmt::format("{}{}", (row == 0 ? "" : "\n"), "[ ");
435+
for (size_t col{ 0 }; col < arr.width_; ++col) {
436+
os << fmt::format("{0}{2:>{1}}", (col == 0 ? "" : ", "), column_widths[col], arr.at(row, col));
437+
}
438+
os << fmt::format("{}", " ]");
439+
}
440+
}
441+
return os;
442+
}
429443

444+
private:
430445
std::vector<T> data_;
431446
size_type width_;
432447
size_type height_;
433448
};
434449
} // namespace tmcppc::data_structures
435450

436451

452+
// fmt formatters
437453
template <rtc::print::printable T>
438454
struct fmt::is_range<tmcppc::data_structures::array_2d<T>, char> : std::false_type {};
439-
440-
441-
template <rtc::print::printable T>
442-
struct fmt::formatter<tmcppc::data_structures::array_2d<T>> {
443-
template <typename ParseContext>
444-
constexpr auto parse(ParseContext& ctx) {
445-
return ctx.begin();
446-
}
447-
448-
template <typename FormatContext>
449-
auto format(const tmcppc::data_structures::array_2d<T>& arr, FormatContext& ctx) const -> decltype(ctx.out()) {
450-
if (arr.empty()) {
451-
fmt::format_to(ctx.out(), "{}", "[]");
452-
} else {
453-
auto column_widths{ get_column_widths(arr) };
454-
455-
for (size_t row{ 0 }; row < arr.height_; ++row) {
456-
fmt::format_to(ctx.out(), "{}{}", (row == 0 ? "" : "\n"), "[ ");
457-
for (size_t col{ 0 }; col < arr.width_; ++col) {
458-
fmt::format_to(ctx.out(), "{0}{2:>{1}}", (col == 0 ? "" : ", "), column_widths[col], arr.at(row, col));
459-
}
460-
fmt::format_to(ctx.out(), "{}", " ]");
461-
}
462-
}
463-
return ctx.out();
464-
}
465-
};
466-
467-
468455
template <rtc::print::printable T>
469-
std::ostream& operator<<(std::ostream& os, const tmcppc::data_structures::array_2d<T>& arr) {
470-
fmt::print(os, "{}", arr);
471-
return os;
472-
}
456+
struct fmt::formatter<tmcppc::data_structures::array_2d<T>> : fmt::ostream_formatter {};

include/the_modern_c++_challenge/chapter_02_language_features/ipv4.h

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
#include <string>
1717

1818

19+
// fmt formatter
20+
namespace tmcppc::network { class ipv4; }
21+
template <>
22+
struct fmt::formatter<tmcppc::network::ipv4> : fmt::ostream_formatter {};
23+
24+
1925
namespace tmcppc::network {
2026
struct invalid_ipv4_address_error : public std::runtime_error {
2127
explicit invalid_ipv4_address_error(const std::string& address) : std::runtime_error{ "" } {
@@ -65,7 +71,9 @@ namespace tmcppc::network {
6571
: octets_{ o0, o1, o2, o3 }
6672
{}
6773

68-
[[nodiscard]] std::string to_string() const;
74+
[[nodiscard]] std::string to_string() const {
75+
return fmt::format("{}", *this);
76+
}
6977

7078
[[nodiscard]] constexpr unsigned long to_ulong() const noexcept {
7179
return static_cast<unsigned long>((octets_[0] << 24) | (octets_[1] << 16) | (octets_[2] << 8) | octets_[3]);
@@ -82,7 +90,7 @@ namespace tmcppc::network {
8290
return tmp;
8391
}
8492

85-
private:
93+
public:
8694
friend bool operator==(const ipv4& lhs, const ipv4& rhs) {
8795
return lhs.octets_ == rhs.octets_;
8896
}
@@ -139,30 +147,6 @@ namespace tmcppc::network {
139147
}
140148

141149
private:
142-
friend struct fmt::formatter<ipv4>;
143-
144150
std::array<std::uint8_t, 4> octets_{};
145151
};
146152
} // namespace tmcppc::network
147-
148-
149-
template <>
150-
struct fmt::formatter<tmcppc::network::ipv4> {
151-
template <typename ParseContext>
152-
constexpr auto parse(ParseContext& ctx) {
153-
return ctx.begin();
154-
}
155-
156-
template <typename FormatContext>
157-
auto format(const tmcppc::network::ipv4& address, FormatContext& ctx) const -> decltype(ctx.out()) {
158-
return fmt::format_to(ctx.out(), "{}.{}.{}.{}",
159-
address.octets_[0], address.octets_[1], address.octets_[2], address.octets_[3]);
160-
}
161-
};
162-
163-
164-
namespace tmcppc::network {
165-
[[nodiscard]] inline std::string ipv4::to_string() const {
166-
return fmt::format("{}", *this);
167-
}
168-
} // namespace tmcppc::network

include/the_modern_c++_challenge/chapter_02_language_features/temperature/v1/temperature.h

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -66,24 +66,22 @@ namespace tmcppc::temperature::v1 {
6666
return *this;
6767
}
6868

69+
friend std::ostream& operator<<(std::ostream& os, const temperature<Rep_>& t) {
70+
const auto& s{ t.scale_ };
71+
if (s == tmcppc::temperature::v1::scale_t::invalid) {
72+
return os << fmt::format("{}", to_string(s));
73+
}
74+
return os << fmt::format("{:.2f} {}", t.value_, to_string(s));
75+
}
76+
6977
[[nodiscard]] Rep_ value() const noexcept { return value_; }
7078
[[nodiscard]] scale_t scale() const noexcept { return scale_; }
7179

7280
private:
73-
friend struct fmt::formatter<temperature>;
74-
7581
Rep_ value_{ 0 };
7682
enum scale_t scale_{ scale_t::invalid };
7783
};
7884

79-
// Operator insertion
80-
//
81-
template <typename Rep_>
82-
std::ostream& operator<<(std::ostream& os, const temperature<Rep_>& t) {
83-
fmt::print(os, "{}", t);
84-
return os;
85-
}
86-
8785
// Conversions
8886
//
8987
// C to F: (C * 9/5) + 32
@@ -217,19 +215,6 @@ namespace tmcppc::temperature::v1 {
217215
} // namespace tmcppc::temperature::v1
218216

219217

218+
// fmt formatter
220219
template <typename Rep_>
221-
struct fmt::formatter<tmcppc::temperature::v1::temperature<Rep_>> {
222-
template <typename ParseContext>
223-
constexpr auto parse(ParseContext& ctx) {
224-
return ctx.begin();
225-
}
226-
227-
template <typename FormatContext>
228-
auto format(const tmcppc::temperature::v1::temperature<Rep_>& t, FormatContext& ctx) const -> decltype(ctx.out()) {
229-
const auto& s{ t.scale() };
230-
if (s == tmcppc::temperature::v1::scale_t::invalid) {
231-
return fmt::format_to(ctx.out(), "{}", to_string(s));
232-
}
233-
return fmt::format_to(ctx.out(), "{:.2f} {}", t.value(), to_string(s));
234-
}
235-
};
220+
struct fmt::formatter<tmcppc::temperature::v1::temperature<Rep_>> : fmt::ostream_formatter {};

include/the_modern_c++_challenge/chapter_02_language_features/temperature/v2/temperature.h

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,15 @@ namespace tmcppc::temperature::v2 {
5555
//
5656
template <typename Rep_>
5757
std::ostream& operator<<(std::ostream& os, const temperature<Rep_, scale_t::celsius>& t) {
58-
fmt::print(os, "{:.2f} Celsius", t.value());
59-
return os;
58+
return os << fmt::format("{:.2f} Celsius", t.value());
6059
}
6160
template <typename Rep_>
6261
std::ostream& operator<<(std::ostream& os, const temperature<Rep_, scale_t::fahrenheit>& t) {
63-
fmt::print(os, "{:.2f} Fahrenheit", t.value());
64-
return os;
62+
return os << fmt::format("{:.2f} Fahrenheit", t.value());
6563
}
6664
template <typename Rep_>
6765
std::ostream& operator<<(std::ostream& os, const temperature<Rep_, scale_t::kelvin>& t) {
68-
fmt::print(os, "{:.2f} Kelvin", t.value());
69-
return os;
66+
return os << fmt::format("{:.2f} Kelvin", t.value());
7067
}
7168

7269
// Conversions
@@ -192,47 +189,10 @@ namespace tmcppc::temperature::v2 {
192189
} // namespace tmcppc::temperature::v2
193190

194191

192+
// fmt formatters
195193
template <typename Rep_>
196-
struct fmt::formatter<tmcppc::temperature::v2::temperature<Rep_, tmcppc::temperature::v2::scale_t::celsius>> {
197-
template <typename ParseContext>
198-
constexpr auto parse(ParseContext& ctx) {
199-
return ctx.begin();
200-
}
201-
202-
template <typename FormatContext>
203-
auto format(const tmcppc::temperature::v2::temperature<Rep_, tmcppc::temperature::v2::scale_t::celsius>& t,
204-
FormatContext& ctx) const -> decltype(ctx.out()) {
205-
206-
return fmt::format_to(ctx.out(), "{:.2f} Celsius", t.value());
207-
}
208-
};
209-
194+
struct fmt::formatter<tmcppc::temperature::v2::temperature<Rep_, tmcppc::temperature::v2::scale_t::celsius>> : fmt::ostream_formatter {};
210195
template <typename Rep_>
211-
struct fmt::formatter<tmcppc::temperature::v2::temperature<Rep_, tmcppc::temperature::v2::scale_t::fahrenheit>> {
212-
template <typename ParseContext>
213-
constexpr auto parse(ParseContext& ctx) {
214-
return ctx.begin();
215-
}
216-
217-
template <typename FormatContext>
218-
auto format(const tmcppc::temperature::v2::temperature<Rep_, tmcppc::temperature::v2::scale_t::fahrenheit>& t,
219-
FormatContext& ctx) const -> decltype(ctx.out()) {
220-
221-
return fmt::format_to(ctx.out(), "{:.2f} Fahrenheit", t.value());
222-
}
223-
};
224-
196+
struct fmt::formatter<tmcppc::temperature::v2::temperature<Rep_, tmcppc::temperature::v2::scale_t::fahrenheit>> : fmt::ostream_formatter {};
225197
template <typename Rep_>
226-
struct fmt::formatter<tmcppc::temperature::v2::temperature<Rep_, tmcppc::temperature::v2::scale_t::kelvin>> {
227-
template <typename ParseContext>
228-
constexpr auto parse(ParseContext& ctx) {
229-
return ctx.begin();
230-
}
231-
232-
template <typename FormatContext>
233-
auto format(const tmcppc::temperature::v2::temperature<Rep_, tmcppc::temperature::v2::scale_t::kelvin>& t,
234-
FormatContext& ctx) const -> decltype(ctx.out()) {
235-
236-
return fmt::format_to(ctx.out(), "{:.2f} Kelvin", t.value());
237-
}
238-
};
198+
struct fmt::formatter<tmcppc::temperature::v2::temperature<Rep_, tmcppc::temperature::v2::scale_t::kelvin>> : fmt::ostream_formatter {};

include/the_modern_c++_challenge/chapter_03_strings_and_regular_expressions/url.h

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,29 @@ namespace tmcppc::network {
6767

6868
auto operator<=>(const url& other) const = default;
6969

70-
private:
71-
friend struct fmt::formatter<url>;
70+
friend std::ostream& operator<<(std::ostream& os, const tmcppc::network::url& u) {
71+
os << fmt::format("[\n");
72+
os << fmt::format("\tProtocol: {}\n", u.protocol_);
73+
if (u.login_.has_value()) {
74+
os << fmt::format("\tLogin: {}\n", u.login_.value());
75+
}
76+
os << fmt::format("\tDomain: {}\n", u.domain_);
77+
if (u.port_.has_value()) {
78+
os << fmt::format("\tPort: {}\n", u.port_.value());
79+
}
80+
if (u.path_.has_value()) {
81+
os << fmt::format("\tPath: {}\n", u.path_.value());
82+
}
83+
if (u.query_.has_value()) {
84+
os << fmt::format("\tQuery: {}\n", u.query_.value());
85+
}
86+
if (u.fragment_.has_value()) {
87+
os << fmt::format("\tFragment: {}\n", u.fragment_.value());
88+
}
89+
return os << fmt::format("]");
90+
}
7291

92+
private:
7393
std::string protocol_;
7494
std::optional<std::string> login_;
7595
std::string domain_;
@@ -81,39 +101,6 @@ namespace tmcppc::network {
81101
} // namespace tmcppc::network
82102

83103

104+
// fmt formatter
84105
template <>
85-
struct fmt::formatter<tmcppc::network::url> {
86-
template <typename ParseContext>
87-
constexpr auto parse(ParseContext& ctx) {
88-
return ctx.begin();
89-
}
90-
91-
template <typename FormatContext>
92-
auto format(const tmcppc::network::url& u, FormatContext& ctx) const -> decltype(ctx.out()) {
93-
fmt::format_to(ctx.out(), "[\n");
94-
fmt::format_to(ctx.out(), "\tProtocol: {}\n", u.protocol_);
95-
if (u.login_.has_value()) {
96-
fmt::format_to(ctx.out(), "\tLogin: {}\n", u.login_.value());
97-
}
98-
fmt::format_to(ctx.out(), "\tDomain: {}\n", u.domain_);
99-
if (u.port_.has_value()) {
100-
fmt::format_to(ctx.out(), "\tPort: {}\n", u.port_.value());
101-
}
102-
if (u.path_.has_value()) {
103-
fmt::format_to(ctx.out(), "\tPath: {}\n", u.path_.value());
104-
}
105-
if (u.query_.has_value()) {
106-
fmt::format_to(ctx.out(), "\tQuery: {}\n", u.query_.value());
107-
}
108-
if (u.fragment_.has_value()) {
109-
fmt::format_to(ctx.out(), "\tFragment: {}\n", u.fragment_.value());
110-
}
111-
fmt::format_to(ctx.out(), "]");
112-
return ctx.out();
113-
}
114-
};
115-
116-
inline std::ostream& operator<<(std::ostream& os, const tmcppc::network::url& u) {
117-
fmt::print(os, "{}", u);
118-
return os;
119-
}
106+
struct fmt::formatter<tmcppc::network::url> : fmt::ostream_formatter {};

0 commit comments

Comments
 (0)