@@ -286,10 +286,13 @@ using __uchar = unsigned char; // normally use u8 instead
286
286
// -----------------------------------------------------------------------
287
287
//
288
288
289
- constexpr auto max (auto ... values) {
289
+ inline constexpr auto max (auto ... values) {
290
290
return std::max ( { values... } );
291
291
}
292
292
293
+ template <class T , class ... Ts>
294
+ inline constexpr auto is_any = std::disjunction_v<std::is_same<T, Ts>...>;
295
+
293
296
294
297
// -----------------------------------------------------------------------
295
298
//
@@ -781,6 +784,108 @@ class out {
781
784
}(PARAM1)
782
785
783
786
787
+ // -----------------------------------------------------------------------
788
+ //
789
+ // to_string for string interpolation
790
+ //
791
+ // -----------------------------------------------------------------------
792
+ //
793
+ inline auto to_string (...) -> std::string
794
+ {
795
+ return " (customize me - no cpp2::to_string overload exists for this type)" ;
796
+ }
797
+
798
+ inline auto to_string (std::same_as<std::any> auto const &) -> std::string
799
+ {
800
+ return " std::any" ;
801
+ }
802
+
803
+ inline auto to_string (bool b) -> std::string
804
+ {
805
+ return b ? " true" : " false" ;
806
+ }
807
+
808
+ template <typename T>
809
+ inline auto to_string (T const & t) -> std::string
810
+ requires requires { std::to_string (t); }
811
+ {
812
+ return std::to_string (t);
813
+ }
814
+
815
+ inline auto to_string (char const & t) -> std::string
816
+ {
817
+ return std::string{t};
818
+ }
819
+
820
+ inline auto to_string (char const * s) -> std::string
821
+ {
822
+ return std::string{s};
823
+ }
824
+
825
+ inline auto to_string (std::string const & s) -> std::string const &
826
+ {
827
+ return s;
828
+ }
829
+
830
+ template <typename T>
831
+ inline auto to_string (T const & sv) -> std::string
832
+ requires (std::is_convertible_v<T, std::string_view>
833
+ && !std::is_convertible_v<T, const char *>)
834
+ {
835
+ return std::string{sv};
836
+ }
837
+
838
+ template <typename ... Ts>
839
+ inline auto to_string (std::variant<Ts...> const & v) -> std::string;
840
+
841
+ template < typename T, typename U>
842
+ inline auto to_string (std::pair<T,U> const & p) -> std::string;
843
+
844
+ template < typename ... Ts>
845
+ inline auto to_string (std::tuple<Ts...> const & t) -> std::string;
846
+
847
+ template <typename T>
848
+ inline auto to_string (std::optional<T> const & o) -> std::string {
849
+ if (o.has_value ()) {
850
+ return cpp2::to_string (o.value ());
851
+ }
852
+ return " (empty)" ;
853
+ }
854
+
855
+ template <typename ... Ts>
856
+ inline auto to_string (std::variant<Ts...> const & v) -> std::string
857
+ {
858
+ if (v.valueless_by_exception ()) return " (empty)" ;
859
+ // Need to guard this with is_any otherwise the get_if is illegal
860
+ if constexpr (is_any<std::monostate, Ts...>) if (std::get_if<std::monostate>(&v) != nullptr ) return " (empty)" ;
861
+
862
+ return std::visit ([](auto && arg) -> std::string {
863
+ return cpp2::to_string (arg);
864
+ }, v);
865
+ }
866
+
867
+ template < typename T, typename U>
868
+ inline auto to_string (std::pair<T,U> const & p) -> std::string
869
+ {
870
+ return " (" + cpp2::to_string (p.first ) + " , " + cpp2::to_string (p.second ) + " )" ;
871
+ }
872
+
873
+ template < typename ... Ts>
874
+ inline auto to_string (std::tuple<Ts...> const & t) -> std::string
875
+ {
876
+ if constexpr (sizeof ...(Ts) == 0 ) {
877
+ return " ()" ;
878
+ } else {
879
+ std::string out = " (" + cpp2::to_string (std::get<0 >(t));
880
+ std::apply ([&out](auto &&, auto &&... args) {
881
+ ((out += " , " + cpp2::to_string (args)), ...);
882
+ }, t);
883
+ out += " )" ;
884
+ return out;
885
+ }
886
+ }
887
+
888
+
784
889
// -----------------------------------------------------------------------
785
890
//
786
891
// is and as
@@ -1000,9 +1105,20 @@ auto as( X& x ) -> decltype(auto) {
1000
1105
return x;
1001
1106
}
1002
1107
1108
+
1109
+ template < typename C, typename X >
1110
+ auto as (X const & x) -> C
1111
+ requires (std::is_same_v<C, std::string> && std::is_integral_v<X>)
1112
+ {
1113
+ return cpp2::to_string (x);
1114
+ }
1115
+
1116
+
1003
1117
template < typename C, typename X >
1004
1118
auto as ( X const & x ) -> auto
1005
- requires (!std::is_same_v<C, X> && !std::is_base_of_v<C, X> && requires { C{x}; })
1119
+ requires (!std::is_same_v<C, X> && !std::is_base_of_v<C, X> && requires { C{x}; }
1120
+ && !(std::is_same_v<C, std::string> && std::is_integral_v<X>) // exclude above case
1121
+ )
1006
1122
{
1007
1123
// Experiment: Recognize the nested `::value_type` pattern for some dynamic library types
1008
1124
// like std::optional, and try to prevent accidental narrowing conversions even when
@@ -1158,9 +1274,6 @@ constexpr auto is( std::variant<Ts...> const& x, auto const& value ) -> bool
1158
1274
1159
1275
// as
1160
1276
//
1161
- template <class T , class ... Ts>
1162
- inline constexpr auto is_any = std::disjunction_v<std::is_same<T, Ts>...>;
1163
-
1164
1277
template <typename T, typename ... Ts>
1165
1278
auto is ( std::variant<Ts...> const & x ) {
1166
1279
if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as< 0 >(x)), T >) { if (x.index () == 0 ) return true ; }
@@ -1424,115 +1537,6 @@ class finally
1424
1537
};
1425
1538
1426
1539
1427
- // -----------------------------------------------------------------------
1428
- //
1429
- // to_string for string interpolation
1430
- //
1431
- // -----------------------------------------------------------------------
1432
- //
1433
- inline auto to_string (...) -> std::string {
1434
- return " (customize me - no cpp2::to_string overload exists for this type)" ;
1435
- }
1436
-
1437
- inline auto to_string (std::same_as<std::any> auto const &) -> std::string {
1438
- return " std::any" ;
1439
- }
1440
-
1441
- template <typename T>
1442
- inline auto to_string (T const & t) -> std::string
1443
- requires requires { std::to_string (t); }
1444
- {
1445
- return std::to_string (t);
1446
- }
1447
-
1448
- inline auto to_string (char const & t) -> std::string
1449
- {
1450
- return std::string{t};
1451
- }
1452
-
1453
- inline auto to_string (char const * s) -> std::string
1454
- {
1455
- return std::string{s};
1456
- }
1457
-
1458
- inline auto to_string (std::string const & s) -> std::string const &
1459
- {
1460
- return s;
1461
- }
1462
-
1463
- template <typename T>
1464
- inline auto to_string (T const & sv) -> std::string
1465
- requires (std::is_convertible_v<T, std::string_view>
1466
- && !std::is_convertible_v<T, const char *>)
1467
- {
1468
- return std::string{sv};
1469
- }
1470
-
1471
- template <typename ... Ts>
1472
- inline auto to_string (std::variant<Ts...> const & v) -> std::string;
1473
-
1474
- template < typename T, typename U>
1475
- inline auto to_string (std::pair<T,U> const & p) -> std::string;
1476
-
1477
- template < typename ... Ts>
1478
- inline auto to_string (std::tuple<Ts...> const & t) -> std::string;
1479
-
1480
- template <typename T>
1481
- inline auto to_string (std::optional<T> const & o) -> std::string {
1482
- if (o.has_value ()) {
1483
- return cpp2::to_string (o.value ());
1484
- }
1485
- return " (empty)" ;
1486
- }
1487
-
1488
- template <typename ... Ts>
1489
- inline auto to_string (std::variant<Ts...> const & v) -> std::string
1490
- {
1491
- if (v.valueless_by_exception ()) return " (empty)" ;
1492
- // Need to guard this with is_any otherwise the get_if is illegal
1493
- if constexpr (is_any<std::monostate, Ts...>) if (std::get_if<std::monostate>(&v) != nullptr ) return " (empty)" ;
1494
-
1495
- return std::visit ([](auto && arg) -> std::string {
1496
- return cpp2::to_string (arg);
1497
- }, v);
1498
- }
1499
-
1500
- template < typename T, typename U>
1501
- inline auto to_string (std::pair<T,U> const & p) -> std::string
1502
- {
1503
- return " (" + cpp2::to_string (p.first ) + " , " + cpp2::to_string (p.second ) + " )" ;
1504
- }
1505
-
1506
- template < typename ... Ts>
1507
- inline auto to_string (std::tuple<Ts...> const & t) -> std::string
1508
- {
1509
- if constexpr (sizeof ...(Ts) == 0 ) {
1510
- return " ()" ;
1511
- } else {
1512
- std::string out = " (" + cpp2::to_string (std::get<0 >(t));
1513
- std::apply ([&out](auto &&, auto &&... args) {
1514
- ((out += " , " + cpp2::to_string (args)), ...);
1515
- }, t);
1516
- out += " )" ;
1517
- return out;
1518
- }
1519
- }
1520
-
1521
-
1522
- // -----------------------------------------------------------------------
1523
- //
1524
- // and "as std::string" for the same cases
1525
- //
1526
- template < typename C >
1527
- auto as (auto & x) -> C
1528
- requires (std::is_same_v<C, std::string>
1529
- && requires { cpp2::to_string (x); })
1530
- {
1531
- return cpp2::to_string (x);
1532
- }
1533
-
1534
-
1535
-
1536
1540
// -----------------------------------------------------------------------
1537
1541
//
1538
1542
// args: see main() arguments as vector<string_view>
0 commit comments