Skip to content

Commit cced142

Browse files
committed
Add to_string support for types like filesystem::path and complex that support << streaming
And simplify by converting the default implementations from overloads into a merged function with if-constexpr cases
1 parent a76e23b commit cced142

File tree

7 files changed

+55
-55
lines changed

7 files changed

+55
-55
lines changed

include/cpp2util.h

Lines changed: 45 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,73 +1190,63 @@ struct nonesuch_ {
11901190
};
11911191
constexpr inline nonesuch_ nonesuch;
11921192

1193-
inline auto to_string([[maybe_unused]] auto const& _) -> std::string
1194-
{
1195-
return "(customize me - no cpp2::to_string overload exists for this type)";
1196-
}
1197-
1198-
inline auto to_string(nonesuch_) -> std::string
1193+
// Suppress spurious MSVC warnings about unreachable code
1194+
#ifdef _MSC_VER
1195+
#pragma warning( push )
1196+
#pragma warning( disable : 4702 )
1197+
#endif
1198+
inline auto to_string(auto const& x) -> std::string
11991199
{
1200-
return "(invalid type)";
1201-
}
1200+
// Handle degenerate case
1201+
if constexpr (std::is_same_v<CPP2_TYPEOF(x), std::string>) {
1202+
return x;
1203+
}
12021204

1203-
inline auto to_string(std::same_as<std::any> auto const&) -> std::string
1204-
{
1205-
return "std::any";
1206-
}
1205+
// Else customize bool (prefer this over << to avoid std::boolalpha)
1206+
if constexpr( std::is_same_v<CPP2_TYPEOF(x), bool> ) {
1207+
return x ? "true" : "false";
1208+
}
12071209

1208-
inline auto to_string(bool b) -> std::string
1209-
{
1210-
return b ? "true" : "false";
1211-
}
1210+
// Else customize char (before int)
1211+
if constexpr (std::is_same_v<CPP2_TYPEOF(x), char>) {
1212+
return std::string{ x };
1213+
}
12121214

1213-
template<typename T>
1214-
inline auto to_string(T const& t) -> std::string
1215-
requires requires { std::to_string(t); }
1216-
{
1217-
return std::to_string(t);
1218-
}
1215+
// Else customize char*
1216+
if constexpr (std::is_same_v<CPP2_TYPEOF(x), const char*>) {
1217+
return std::string{ x };
1218+
}
12191219

1220-
//// We'd like to add this convenience, which would support std::filesystem::path() and similar.
1221-
////
1222-
//// TODO: As written, this one would make some cases ambiguous. We should rewrite these
1223-
//// common to_string functions as a single template with 'if constexpr' alternatives,
1224-
//// as was done with 'is', and then this will be simpler.
1225-
//template<typename T>
1226-
//inline auto to_string(T const& t) -> std::string
1227-
// requires std::is_convertible_v<decltype((std::stringstream() << t).str()), std::string>
1228-
//{
1229-
// return (std::stringstream() << t).str();
1230-
//}
1220+
// Else prefer string_view if available
1221+
if constexpr (std::is_convertible_v<CPP2_TYPEOF(x), std::string_view>) {
1222+
return std::string{ x };
1223+
}
12311224

1232-
template<typename T>
1233-
inline auto to_string(T const& t) -> std::string
1234-
requires std::is_convertible_v<decltype(t.to_string()), std::string>
1235-
{
1236-
return t.to_string();
1237-
}
1225+
// Else prefer std::to_string if available
1226+
if constexpr( requires { std::to_string(x); } ) {
1227+
return std::to_string(x);
1228+
}
12381229

1239-
inline auto to_string(char const& t) -> std::string
1240-
{
1241-
return std::string{t};
1242-
}
1230+
// Else prefer streaming << if available
1231+
if constexpr( requires { { (std::stringstream() << x).str() } -> std::convertible_to<std::string>; } ) {
1232+
return (std::stringstream() << x).str();
1233+
}
12431234

1244-
inline auto to_string(char const* s) -> std::string
1245-
{
1246-
return std::string{s};
1247-
}
1235+
// Else complain about a 'nonesuch' result
1236+
if constexpr( std::is_same_v<CPP2_TYPEOF(x), nonesuch_> ) {
1237+
return "(invalid type)";
1238+
}
12481239

1249-
inline auto to_string(std::string const& s) -> std::string const&
1250-
{
1251-
return s;
1240+
// Else prompt to customize
1241+
return "(customize me - no cpp2::to_string overload exists for this type)";
12521242
}
1243+
#ifdef _MSC_VER
1244+
#pragma warning( pop )
1245+
#endif
12531246

1254-
template<typename T>
1255-
inline auto to_string(T const& sv) -> std::string
1256-
requires (std::is_convertible_v<T, std::string_view>
1257-
&& !std::is_convertible_v<T, const char*>)
1247+
inline auto to_string(std::same_as<std::any> auto const&) -> std::string
12581248
{
1259-
return std::string{sv};
1249+
return "std::any";
12601250
}
12611251

12621252
template <typename... Ts>

regression-tests/pure2-interpolation.cpp2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@ main: ()->int = {
2828
std::cout << "(x.name():20)$ color (x.color():10)$ price (x.price(): <10.2f)$ in stock = (x.count() > 0)$\n";
2929
}
3030

31+
ri: std::complex = ( 1.2, 3.4 );
32+
std::cout << "complex: (ri)$\n"; // works on GCC 11.2+ and Clang 13+
33+
// prints "customize me" on GCC 11.1 and Clang 12
3134
}

regression-tests/test-results/clang-12-c++20/pure2-interpolation.cpp.execution

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ pl(ug$h
1010
0pl(ug$h
1111
Dog kennel color mauve price 3.14 in stock = true
1212
Dog kennel color mauve price 3.140000 in stock = true
13+
complex: (customize me - no cpp2::to_string overload exists for this type)

regression-tests/test-results/gcc-10-c++20/pure2-interpolation.cpp.execution

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ pl(ug$h
1010
0pl(ug$h
1111
Dog kennel color mauve price 3.14 in stock = true
1212
Dog kennel color mauve price 3.140000 in stock = true
13+
complex: (customize me - no cpp2::to_string overload exists for this type)

regression-tests/test-results/gcc-14-c++2b/pure2-interpolation.cpp.execution

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ pl(ug$h
1010
0pl(ug$h
1111
Dog kennel color mauve price 3.14 in stock = true
1212
Dog kennel color mauve price 3.14 in stock = true
13+
complex: (1.2,3.4)

regression-tests/test-results/msvc-2022-c++latest/pure2-interpolation.cpp.execution

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ pl(ug$h
1010
0pl(ug$h
1111
Dog kennel color mauve price 3.14 in stock = true
1212
Dog kennel color mauve price 3.14 in stock = true
13+
complex: (1.2,3.4)

regression-tests/test-results/pure2-interpolation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,8 @@ auto const& x{item()};
7171
}
7272

7373
#line 31 "pure2-interpolation.cpp2"
74+
std::complex ri {1.2, 3.4};
75+
std::cout << ("complex: " + cpp2::to_string(cpp2::move(ri)) + "\n");// works on GCC 11.2+ and Clang 13+
76+
// prints "customize me" on GCC 11.1 and Clang 12
7477
}
7578

0 commit comments

Comments
 (0)