@@ -702,6 +702,23 @@ struct nonesuch_ {
702
702
};
703
703
static nonesuch_ nonesuch;
704
704
705
+ // Most of the 'as' casts are <To, From> so use that order here
706
+ // If it's confusing, we can switch this to <From, To>
707
+ template < typename To, typename From >
708
+ inline constexpr auto is_narrowing_v =
709
+ // [dcl.init.list] 7.1
710
+ (std::is_floating_point_v<From> && std::is_integral_v<To>) ||
711
+ // [dcl.init.list] 7.2
712
+ (std::is_floating_point_v<From> && std::is_floating_point_v<To> && sizeof (From) > sizeof (To)) ||
713
+ // [dcl.init.list] 7.3
714
+ (std::is_integral_v<From> && std::is_floating_point_v<To>) ||
715
+ (std::is_enum_v<From> && std::is_floating_point_v<To>) ||
716
+ // [dcl.init.list] 7.4
717
+ (std::is_integral_v<From> && std::is_integral_v<To> && sizeof (From) > sizeof (To)) ||
718
+ (std::is_enum_v<From> && std::is_integral_v<To> && sizeof (From) > sizeof (To)) ||
719
+ // [dcl.init.list] 7.5
720
+ (std::is_pointer_v<From> && std::is_same_v<To, bool >);
721
+
705
722
template <typename ... Ts>
706
723
inline constexpr auto program_violates_type_safety_guarantee = sizeof ...(Ts) < 0 ;
707
724
@@ -781,7 +798,7 @@ auto as( X const& x ) -> decltype(auto) {
781
798
782
799
template < typename C, typename X >
783
800
auto as ( X const & x ) -> auto
784
- requires (!std::is_same_v<C, X> && requires { C{x}; })
801
+ requires (!std::is_same_v<C, X> && requires { C{x}; } && !is_narrowing_v<C, X> )
785
802
{
786
803
return C{x};
787
804
}
0 commit comments