File tree Expand file tree Collapse file tree 1 file changed +29
-3
lines changed Expand file tree Collapse file tree 1 file changed +29
-3
lines changed Original file line number Diff line number Diff line change @@ -552,9 +552,35 @@ auto is( X const& x ) -> bool {
552
552
// -------------------------------------------------------------------------------------------------------------
553
553
// Built-in as (partial)
554
554
//
555
- template < typename C >
556
- auto as (...) -> auto {
557
- return nonesuch;
555
+ template <typename ... Ts>
556
+ inline constexpr auto program_violates_type_safety_guarantee = sizeof ...(Ts) < 0 ;
557
+
558
+ template < typename C, typename ... Ts >
559
+ auto as (Ts... ts) -> auto {
560
+ static_assert (program_violates_type_safety_guarantee<Ts...>, " safe 'as' cast is not defined" );
561
+ }
562
+
563
+ struct narrowing_error : public std ::exception
564
+ {
565
+ const char * what () const noexcept override { return " narrowing_error" ; }
566
+ };
567
+
568
+ template < typename C, typename X >
569
+ requires ( !std::is_same_v<C, X>
570
+ && std::is_arithmetic_v<C> && std::is_arithmetic_v<X>
571
+ )
572
+ auto as ( const X& x ) -> auto
573
+ requires (!requires { C{x}; })
574
+ {
575
+ constexpr const bool is_different_signedness = (std::is_signed_v<C> != std::is_signed_v<X>);
576
+ const C value = static_cast <C>(x);
577
+
578
+ if (static_cast <X>(value) != x || (is_different_signedness && ((value < C{}) != (x < X{}))))
579
+ {
580
+ throw narrowing_error{};
581
+ }
582
+
583
+ return value;
558
584
}
559
585
560
586
template < typename C, typename X >
You can’t perform that action at this time.
0 commit comments