Skip to content

Commit f161425

Browse files
committed
Add test for typle as cast aggregate has no to_string overload
1 parent de8a181 commit f161425

6 files changed

+64
-3
lines changed

include/cpp2util.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,13 @@ inline auto to_string(std::tuple<Ts...> const& t) -> std::string
12511251
} else {
12521252
std::string out = "(" + cpp2::to_string(std::get<0>(t));
12531253
std::apply([&out](auto&&, auto&&... args) {
1254-
((out += ", " + cpp2::to_string(args)), ...);
1254+
((out += ", " + []<typename T>(T const& arg) {
1255+
if constexpr (has_to_string_overload<T> || std::is_copy_constructible_v<T>) {
1256+
return cpp2::to_string(arg);
1257+
} else {
1258+
return cpp2::to_string(std::ref(arg)); // cpp2::to_string(...) requires copy constructible type
1259+
}
1260+
}(args)), ...);
12551261
}, t);
12561262
out += ")";
12571263
return out;
@@ -1310,8 +1316,7 @@ constexpr auto has_recursive_to_string_overload(C<Ts...> const&)
13101316
template <std::same_as<std::string> C, has_to_string_overload X>
13111317
requires not_one_of<X, std::string, std::any> && (same_type_as<X, bool> || no_brace_initializable_to<X, C>)
13121318
auto as( X&& x ) {
1313-
if constexpr (specialization_of_template<X, std::variant>
1314-
&& requires {
1319+
if constexpr ( requires {
13151320
{ has_recursive_to_string_overload(x) } -> std::same_as<std::false_type>;
13161321
}
13171322
) {

regression-tests/mixed-overview-of-as-casts.cpp2

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,12 @@ main: () = {
246246
a : std::any = "string" as std::string;
247247
print("std::any{\"string\"} as std::string", (a as std::string), "string");
248248
}
249+
{
250+
t : std::tuple<int, double, std::string> = (42, 3.14, "string");
251+
print("std::tuple{42, 3.14, \"string\"} as std::string", (t as std::string), "(42, 3.140000, string)");
252+
print("cpp2::to_string(std::tuple<int, A>())", cpp2::to_string(std::tuple<int, A>()), "(0, (customize me - no cpp2::to_string overload exists for this type))");
253+
// std::tuple<int, A>() as std::string;
254+
}
249255
}
250256
}
251257

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
main: () = {
2+
std::tuple<int, A>() as std::string;
3+
}
4+
5+
A: type = {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
In file included from mixed-typle-as-cast-aggregate-has-no-to_string-overload.cpp:6:
2+
../../../include/cpp2util.h:2172:9: error: static_assert failed due to requirement 'program_violates_type_safety_guarantee<std::string, std::tuple<int, A>>' "One of aggregate types has no cpp2::to_string overload - if you're sure you want this, use `cpp2::to_string() to force the conversion"
3+
static_assert(
4+
^
5+
mixed-typle-as-cast-aggregate-has-no-to_string-overload.cpp2:2:11: note: in instantiation of function template specialization 'cpp2::as_<std::string, std::tuple<int, A>>' requested here
6+
cpp2::as_<std::string>(std::tuple<int,A>());
7+
^
8+
1 error generated.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
3+
//=== Cpp2 type declarations ====================================================
4+
5+
6+
#include "cpp2util.h"
7+
8+
#line 1 "mixed-typle-as-cast-aggregate-has-no-to_string-overload.cpp2"
9+
10+
#line 5 "mixed-typle-as-cast-aggregate-has-no-to_string-overload.cpp2"
11+
class A;
12+
13+
14+
//=== Cpp2 type definitions and function declarations ===========================
15+
16+
#line 1 "mixed-typle-as-cast-aggregate-has-no-to_string-overload.cpp2"
17+
auto main() -> int;
18+
19+
#line 5 "mixed-typle-as-cast-aggregate-has-no-to_string-overload.cpp2"
20+
class A {
21+
public: A() = default;
22+
public: A(A const&) = delete; /* No 'that' constructor, suppress copy */
23+
public: auto operator=(A const&) -> void = delete;
24+
};
25+
#line 6 "mixed-typle-as-cast-aggregate-has-no-to_string-overload.cpp2"
26+
27+
28+
//=== Cpp2 function definitions =================================================
29+
30+
#line 1 "mixed-typle-as-cast-aggregate-has-no-to_string-overload.cpp2"
31+
auto main() -> int{
32+
#line 2 "mixed-typle-as-cast-aggregate-has-no-to_string-overload.cpp2"
33+
cpp2::as_<std::string>(std::tuple<int,A>());
34+
}
35+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
mixed-typle-as-cast-aggregate-has-no-to_string-overload.cpp2... ok (all Cpp2, passes safety checks)
2+

0 commit comments

Comments
 (0)