@@ -40,6 +40,7 @@ import std.threading;
40
40
#include < iostream>
41
41
#include < cassert>
42
42
#include < variant>
43
+ #include < cstddef>
43
44
#endif
44
45
45
46
@@ -72,20 +73,20 @@ namespace cpp2 {
72
73
struct {
73
74
template <typename T, typename ... Args>
74
75
[[nodiscard]] auto cpp2_new (auto ...args) const -> std::unique_ptr<T> {
75
- return std::make_unique<T>(CPP2_FORWARD (args)...);
76
+ return std::make_unique<T>(std::forward< decltype (args)> (args)...);
76
77
}
77
78
} unique;
78
79
79
80
struct {
80
81
template <typename T, typename ... Args>
81
82
[[nodiscard]] auto cpp2_new (auto ...args) const -> std::shared_ptr<T> {
82
- return std::make_shared<T>(CPP2_FORWARD (args)...);
83
+ return std::make_shared<T>(std::forward< decltype (args)> (args)...);
83
84
}
84
85
} shared;
85
86
86
87
template <typename T, typename ... Args>
87
88
[[nodiscard]] auto cpp2_new (auto ...args) -> std::unique_ptr<T> {
88
- return std::make_unique<T>(CPP2_FORWARD (args)...);
89
+ return std::make_unique<T>(std::forward< decltype (args)> (args)...);
89
90
}
90
91
91
92
@@ -130,8 +131,8 @@ class deferred_init {
130
131
~deferred_init () noexcept { if (init) t.~T (); }
131
132
auto value () noexcept -> T& { assert (init); return t; }
132
133
133
- auto construct (auto ...args) -> void { assert (!init); new (&t) T (CPP2_FORWARD (args)...); init = true ; }
134
- auto construct_list (auto ...args) -> void { assert (!init); new (&t) T{CPP2_FORWARD (args)...}; init = true ; }
134
+ auto construct (auto ...args) -> void { assert (!init); new (&t) T (std::forward< decltype (args)> (args)...); init = true ; }
135
+ auto construct_list (auto ...args) -> void { assert (!init); new (&t) T{std::forward< decltype (args)> (args)...}; init = true ; }
135
136
};
136
137
137
138
template <typename T>
@@ -270,7 +271,7 @@ auto assert_not_null(auto&& p CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> auto&&
270
271
{
271
272
// Checking against a default-constructed value should be fine for iterators too
272
273
// TODO: validate this works for all pointerlike types
273
- Null.expects (p != CPP2_TYPEOF (p){} CPP2_SOURCE_LOCATION_ARG);
274
+ Null.expects (p != CPP2_TYPEOF (p){}, " dynamic null dereference attempt detected " CPP2_SOURCE_LOCATION_ARG);
274
275
return std::forward<decltype (p)>(p);
275
276
}
276
277
@@ -283,82 +284,150 @@ auto assert_not_null(auto&& p CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> auto&&
283
284
//
284
285
#define CPP2_UFCS (FUNCNAME,PARAM1,...) \
285
286
[](auto && obj, auto && ...params) { \
286
- if constexpr (requires { CPP2_FORWARD (obj).FUNCNAME (CPP2_FORWARD (params)...); }) { \
287
- return CPP2_FORWARD (obj).FUNCNAME (CPP2_FORWARD (params)...); \
287
+ if constexpr (requires { std::forward< decltype (obj)>(obj) .FUNCNAME (std::forward< decltype (params)> (params)...); }) { \
288
+ return std::forward< decltype (obj)>(obj) .FUNCNAME (std::forward< decltype (params)> (params)...); \
288
289
} else { \
289
- return FUNCNAME (CPP2_FORWARD (obj), CPP2_FORWARD (params)...); \
290
+ return FUNCNAME (std::forward< decltype (obj)>(obj), std::forward< decltype (params)> (params)...); \
290
291
} \
291
292
}(PARAM1, __VA_ARGS__)
292
293
293
294
#define CPP2_UFCS_0 (FUNCNAME,PARAM1 ) \
294
295
[](auto && obj) { \
295
- if constexpr (requires { CPP2_FORWARD (obj).FUNCNAME (); }) { \
296
- return CPP2_FORWARD (obj).FUNCNAME (); \
296
+ if constexpr (requires { std::forward< decltype (obj)> (obj).FUNCNAME (); }) { \
297
+ return std::forward< decltype (obj)> (obj).FUNCNAME (); \
297
298
} else { \
298
- return FUNCNAME (CPP2_FORWARD (obj)); \
299
+ return FUNCNAME (std::forward< decltype (obj)> (obj)); \
299
300
} \
300
301
}(PARAM1)
301
302
302
303
303
-
304
- /*
305
304
// -----------------------------------------------------------------------
306
305
//
307
306
// is and as
308
307
//
309
308
// -----------------------------------------------------------------------
310
309
//
311
- #include <cstddef>
312
- #include <iostream>
313
- #include <cassert>
310
+ // -------------------------------------------------------------------------------------------------------------
311
+ // Built-in is (partial)
312
+ //
313
+
314
+ // For use when returning "no such thing", such as
315
+ // when customizing is/as for std::variant
316
+ static std::nullptr_t nonesuch = nullptr ;
317
+
318
+ template < typename C, typename X >
319
+ auto is ( X const & ) -> bool {
320
+ return false ;
321
+ }
314
322
315
- #define typeof(x) std::remove_cvref_t<decltype(x)>
323
+ template < typename C, typename X >
324
+ requires std::is_same_v<C, X>
325
+ auto is ( X const & ) -> bool {
326
+ return true ;
327
+ }
328
+
329
+ template < typename C, typename X >
330
+ requires (std::is_base_of_v<C, X> && !std::is_same_v<C,X>)
331
+ auto is ( X const & ) -> bool {
332
+ return true ;
333
+ }
334
+
335
+ template < typename C, typename X >
336
+ requires (std::is_base_of_v<X, C> && !std::is_same_v<C,X>)
337
+ auto is ( X const & x ) -> bool {
338
+ return dynamic_cast <C const *>(&x) != nullptr ;
339
+ }
340
+
341
+ template < typename C, typename X >
342
+ requires (std::is_base_of_v<X, C> && !std::is_same_v<C,X>)
343
+ auto is ( X const * x ) -> bool {
344
+ return dynamic_cast <C const &>(x) != nullptr ;
345
+ }
316
346
317
347
318
348
// -------------------------------------------------------------------------------------------------------------
319
- // Built-in is
349
+ // Built-in as (partial)
320
350
//
321
- template<typename T, typename X>
322
- auto is( X const& x ) {
323
- return false;
351
+ template < typename C, typename X >
352
+ requires std::is_base_of_v<C, X>
353
+ auto as ( X&& x ) -> C&& {
354
+ return std::forward<X>(x);
324
355
}
325
356
326
- template<typename T, typename X>
327
- requires std::is_same_v<T, X>
328
- auto is( X const& x ) {
329
- return true;
357
+ template < typename C, typename X >
358
+ requires (std::is_base_of_v<X, C> && !std::is_same_v<C,X>)
359
+ auto as ( X& x ) -> C& {
360
+ return dynamic_cast <C&>(x);
361
+ }
362
+
363
+ template < typename C, typename X >
364
+ requires (std::is_base_of_v<X, C> && !std::is_same_v<C,X>)
365
+ auto as ( X const & x ) -> C const & {
366
+ return dynamic_cast <C const &>(x);
330
367
}
331
368
369
+ template < typename C, typename X >
370
+ requires (std::is_base_of_v<X, C> && !std::is_same_v<C,X>)
371
+ auto as ( X* x ) -> C* {
372
+ return dynamic_cast <C*>(x);
373
+ }
374
+
375
+ template < typename C, typename X >
376
+ requires (std::is_base_of_v<X, C> && !std::is_same_v<C,X>)
377
+ auto as ( X const * x ) -> C const * {
378
+ return dynamic_cast <C const *>(x);
379
+ }
332
380
333
381
334
382
// -------------------------------------------------------------------------------------------------------------
335
- // variant is and as
383
+ // std:: variant is and as
336
384
//
337
385
template <typename ... Ts>
338
386
constexpr auto operator_is ( std::variant<Ts...> const & x ) {
339
387
return x.index ();
340
388
}
341
389
template <size_t I, typename ... Ts>
342
390
constexpr auto operator_as ( std::variant<Ts...> const & x ) -> auto&& {
343
- return std::get<I>( x );
391
+ if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
392
+ return std::get<I>( x );
393
+ }
394
+ else {
395
+ return nonesuch;
396
+ }
344
397
}
345
398
346
399
template <typename T, typename ... Ts>
347
400
auto is ( std::variant<Ts...> const & x ) {
348
- if constexpr (std::is_same_v< typeof(operator_as<0>(x)), T >) if (x.index() == 0) return true;
349
- if constexpr (std::is_same_v< typeof(operator_as<1>(x)), T >) if (x.index() == 1) return true;
350
- if constexpr (std::is_same_v< typeof(operator_as<2>(x)), T >) if (x.index() == 2) return true;
401
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<0 >(x)), T >) if (x.index () == 0 ) return true ;
402
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<1 >(x)), T >) if (x.index () == 1 ) return true ;
403
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<2 >(x)), T >) if (x.index () == 2 ) return true ;
404
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<3 >(x)), T >) if (x.index () == 3 ) return true ;
405
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<4 >(x)), T >) if (x.index () == 4 ) return true ;
406
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<5 >(x)), T >) if (x.index () == 5 ) return true ;
407
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<6 >(x)), T >) if (x.index () == 6 ) return true ;
408
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<7 >(x)), T >) if (x.index () == 7 ) return true ;
409
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<8 >(x)), T >) if (x.index () == 8 ) return true ;
410
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<9 >(x)), T >) if (x.index () == 9 ) return true ;
351
411
return false ;
352
412
}
353
413
354
414
template <typename T, typename ... Ts>
355
415
auto as ( std::variant<Ts...> const & x ) {
356
- if constexpr (std::is_same_v< typeof(operator_as<0>(x)), T >) if (x.index() == 0) return operator_as<0>(x);
357
- if constexpr (std::is_same_v< typeof(operator_as<1>(x)), T >) if (x.index() == 1) return operator_as<1>(x);
358
- if constexpr (std::is_same_v< typeof(operator_as<2>(x)), T >) if (x.index() == 2) return operator_as<2>(x);
416
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<0 >(x)), T >) if (x.index () == 0 ) return operator_as<0 >(x);
417
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<1 >(x)), T >) if (x.index () == 1 ) return operator_as<1 >(x);
418
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<2 >(x)), T >) if (x.index () == 2 ) return operator_as<2 >(x);
419
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<3 >(x)), T >) if (x.index () == 3 ) return operator_as<3 >(x);
420
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<4 >(x)), T >) if (x.index () == 4 ) return operator_as<4 >(x);
421
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<5 >(x)), T >) if (x.index () == 5 ) return operator_as<5 >(x);
422
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<6 >(x)), T >) if (x.index () == 6 ) return operator_as<2 >(x);
423
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<7 >(x)), T >) if (x.index () == 7 ) return operator_as<3 >(x);
424
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<8 >(x)), T >) if (x.index () == 8 ) return operator_as<4 >(x);
425
+ if constexpr (std::is_same_v< CPP2_TYPEOF (operator_as<9 >(x)), T >) if (x.index () == 9 ) return operator_as<5 >(x);
359
426
throw std::bad_variant_access ();
360
427
}
361
428
429
+
430
+ /*
362
431
//=============================================================================================================
363
432
364
433
int main() {
@@ -394,4 +463,20 @@ int main() {
394
463
using cpp2::cpp2_new;
395
464
396
465
466
+ namespace gsl {
467
+
468
+ // -----------------------------------------------------------------------
469
+ //
470
+ // An implementation of GSL's narrow_cast
471
+ //
472
+ // -----------------------------------------------------------------------
473
+ //
474
+ template <typename To, typename From>
475
+ constexpr auto narrow_cast (From&& from) noexcept -> To
476
+ {
477
+ return static_cast <To>(std::forward<From>(from));
478
+ }
479
+
480
+ }
481
+
397
482
#endif
0 commit comments