From 7bafc1dfc1cb5ca40fd92d2b2df99ea91c221bdc Mon Sep 17 00:00:00 2001 From: Lukas Thomann Date: Tue, 6 Oct 2026 11:46:11 +0200 Subject: [PATCH 1/2] refactor: use std range formatting instead of cth::str::to_string C++23 formats ranges of any formattable type. The cth formatter took over every range, split strings into characters, prefixed the output with cth::str::printable_rng and rejected the std range format specs. --- cth/incl/cth/string.hpp | 43 ----------------------------------- cth/tests/src/string_test.cpp | 33 --------------------------- 2 files changed, 76 deletions(-) diff --git a/cth/incl/cth/string.hpp b/cth/incl/cth/string.hpp index b280429..7ad76e2 100644 --- a/cth/incl/cth/string.hpp +++ b/cth/incl/cth/string.hpp @@ -66,39 +66,6 @@ template } -/** - * @brief formats ranges to string - * @tparam Rng must satisfy rng::static_dim_rng - */ -template requires(rng::static_dim_rng>) -[[nodiscard]] constexpr std::string to_string(Rng&& range) { - static constexpr bool MD_RANGE = mta::md_range; - - decltype(auto) rng = rng::to_viewable(range); - using rng_t = decltype(rng); - - if(std::ranges::empty(rng)) - return {}; - - - std::string string = "["; - for(auto&& element : std::forward(rng)) { - using E = decltype(element); - if constexpr(MD_RANGE) - string.insert_range( - string.end(), - std::format("{}, ", cth::str::to_string(std::forward(element))) - ); - else { - static_assert(std::formattable, "range value type is not formattable"); - string.insert_range(string.end(), std::format("{}, ", std::forward(element))); - } - } - - string.pop_back(); - string.back() = ']'; - return string; -} /** @@ -130,16 +97,6 @@ template< } // namespace cth::str -namespace cth::str { -template -concept printable_rng = rng::viewable_rng && rng::static_dim_rng> && - !cth::mta::constructs_any_of; -} - - -CTH_FORMAT_CPT(cth::str::printable_rng, cth::str::to_string); - - namespace cth::expr::str { template diff --git a/cth/tests/src/string_test.cpp b/cth/tests/src/string_test.cpp index f4975c9..d932ead 100644 --- a/cth/tests/src/string_test.cpp +++ b/cth/tests/src/string_test.cpp @@ -18,39 +18,6 @@ STR_TEST(to_string, range_decline_nonstatic_dim) { EXPECT_FALSE(cth::rng::static_dim_rng); } -STR_TEST(to_string, value_only_rng) { - static constexpr size_t COUNT = 10; - - std::map map{}; - for(size_t i = 0; i < COUNT; i++) - map[i] = i; - - auto view = map | std::views::keys | std::views::filter([](auto const id) { return id % 2 == 0; }); - - auto const result = std::format("{}", view); - EXPECT_EQ("cth::str::printable_rng{[0, 2, 4, 6, 8]}", result); -} - -STR_TEST(to_string, range) { - std::vector const vec = {1, 2, 3, 4, 5}; - std::string const str = cth::str::to_string(vec); - EXPECT_EQ(str, "[1, 2, 3, 4, 5]"); -} - -STR_TEST(to_string, 2drange) { - std::vector> const vec = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; - std::string const str = cth::str::to_string(vec); - EXPECT_EQ(str, "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]"); -} - -STR_TEST(to_string, view) { - std::vector const vec = {1, 2, 3, 4, 5}; - - std::string const str = cth::str::to_string(std::views::all(vec)); - EXPECT_EQ(str, "[1, 2, 3, 4, 5]"); -} - - STR_TEST(to_num, main) { EXPECT_EQ(cth::str::to_num("1234"), 1234u); EXPECT_EQ(cth::str::to_num("1234"), 1234.f); From bf8b082fb9cd2db1973e11aba28baed613598a2d Mon Sep 17 00:00:00 2001 From: Lukas Thomann Date: Tue, 6 Oct 2026 11:53:18 +0200 Subject: [PATCH 2/2] test: format ranges of formattable types with all cth headers included Guards against cth taking over std range formatting again. --- cth/tests/src/format_test.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cth/tests/src/format_test.cpp b/cth/tests/src/format_test.cpp index 10b36e6..121d02b 100644 --- a/cth/tests/src/format_test.cpp +++ b/cth/tests/src/format_test.cpp @@ -2,8 +2,12 @@ #define FMT_TEST(suite, test_name) CTH_EX_TEST(format, suite, test_name) +#include "cth/cth.hpp" #include "cth/string/format.hpp" +#include +#include + namespace test { @@ -61,4 +65,15 @@ FMT_TEST(CTH_FORMAT_CPT, main) { ASSERT_EQ(str, expected); } + +FMT_TEST(range, main) { + std::vector<::test::Test1> const points{{1, 2}, {3, 4}}; + std::vector const words{"oaf", "farthest"}; + std::vector> const nested{{1, 2}, {3}}; + + EXPECT_EQ(std::format("{}", points), "[test::Test1{x: 1, y: 2}, test::Test1{x: 3, y: 4}]"); + EXPECT_EQ(std::format("{}", words), R"(["oaf", "farthest"])"); + EXPECT_EQ(std::format("{::}", words), "[oaf, farthest]"); + EXPECT_EQ(std::format("{}", nested), "[[1, 2], [3]]"); +} }