template<typename T_To, typename T_From> inline constexpr void convert_type_fundamental(T_To& to, constvolatile T_From& from)
{
using namespace std;
if_constexpr_named(cond1, !is_fundamental_or_enum_v<T_To>)
{
rlbox_detail_static_fail_because(
cond1, "Conversion target should be fundamental or enum type");
} else if_constexpr_named(cond2, !is_fundamental_or_enum_v<T_From>)
{
rlbox_detail_static_fail_because(
cond2, "Conversion source should be fundamental or enum type");
} else if_constexpr_named(cond3, is_enum_v<T_To> || is_enum_v<T_From>)
{
static_assert(std::is_same_v<detail::remove_cv_ref_t<T_To>,
detail::remove_cv_ref_t<T_From>>);
to = from;
} else if_constexpr_named(
cond4, is_floating_point_v<T_To> || is_floating_point_v<T_From>)
{
static_assert(is_floating_point_v<T_To> && is_floating_point_v<T_From>); // language coerces different float types
to = from;
} else if_constexpr_named(cond5, is_integral_v<T_To> || is_integral_v<T_From>)
{
static_assert(is_integral_v<T_To> && is_integral_v<T_From>);
constchar* err_msg = "Over/Underflow when converting between integer types";
// Some branches don't use the param
RLBOX_UNUSED(err_msg);
if constexpr (is_signed_v<T_To> == is_signed_v<T_From> && sizeof(T_To) >= sizeof(T_From)) { // Eg: int64_t from int32_t, uint64_t from uint32_t
} elseif constexpr (is_unsigned_v<T_To> && is_unsigned_v<T_From>) { // Eg: uint32_t from uint64_t
dynamic_check(from <= numeric_limits<T_To>::max(), err_msg);
} elseif constexpr (is_signed_v<T_To> && is_signed_v<T_From>) { // Eg: int32_t from int64_t
dynamic_check(from >= numeric_limits<T_To>::min(), err_msg);
dynamic_check(from <= numeric_limits<T_To>::max(), err_msg);
} elseif constexpr (is_unsigned_v<T_To> && is_signed_v<T_From>) { if constexpr (sizeof(T_To) < sizeof(T_From)) { // Eg: uint32_t from int64_t
dynamic_check(from >= 0, err_msg); auto to_max = numeric_limits<T_To>::max();
dynamic_check(from <= static_cast<T_From>(to_max), err_msg);
} else { // Eg: uint32_t from int32_t, uint64_t from int32_t
dynamic_check(from >= 0, err_msg);
}
} elseif constexpr (is_signed_v<T_To> && is_unsigned_v<T_From>) { if constexpr (sizeof(T_To) <= sizeof(T_From)) { // Eg: int32_t from uint32_t, int32_t from uint64_t auto to_max = numeric_limits<T_To>::max();
dynamic_check(from <= static_cast<T_From>(to_max), err_msg);
} else { // Eg: int64_t from uint32_t
}
}
to = static_cast<T_To>(from);
} else
{
constexpr auto unknownCase = !(cond1 || cond2 || cond3 || cond4 || cond5);
rlbox_detail_static_fail_because(
unknownCase, "Unexpected case for convert_type_fundamental");
}
}
template<typename T_To, typename T_From> inline constexpr void convert_type_fundamental_or_array(T_To& to, const T_From& from)
{
using namespace std;
using T_To_C = std_array_to_c_arr_t<T_To>;
using T_From_C = std_array_to_c_arr_t<T_From>;
using T_To_El = remove_all_extents_t<T_To_C>;
using T_From_El = remove_all_extents_t<T_From_C>;
if_constexpr_named(cond1, is_array_v<T_To_C> != is_array_v<T_From_C>)
{
rlbox_detail_static_fail_because(
cond1, "Conversion should not go between array and non array types");
} elseif constexpr (!is_array_v<T_To_C>)
{
convert_type_fundamental(to, from);
} else if_constexpr_named(cond2, !all_extents_same<T_To_C, T_From_C>)
{
rlbox_detail_static_fail_because(
cond2, "Conversion between arrays should have same dimensions");
} else if_constexpr_named(cond3,
is_pointer_v<T_To_El> || is_pointer_v<T_From_El>)
{
rlbox_detail_static_fail_because(cond3, "convert_type_fundamental_or_array " "does not allow arrays of pointers");
} else
{ // Explicitly using size to check for element type as we may be going across // different types of the same width such as void* and uintptr_t if constexpr (sizeof(T_To_El) == sizeof(T_From_El) &&
is_signed_v<T_To_El> == is_signed_v<T_From_El>) { // Sanity check - this should definitely be true
static_assert(sizeof(T_From_C) == sizeof(T_To_C));
std::memcpy(&to, &from, sizeof(T_To_C));
} else { for (size_t i = 0; i < std::extent_v<T_To_C>; i++) {
convert_type_fundamental_or_array(to[i], from[i]);
}
}
}
}
// Some branches don't use the param
RLBOX_UNUSED(example_unsandboxed_ptr);
RLBOX_UNUSED(sandbox_ptr);
using T_To_C = std_array_to_c_arr_t<T_To>;
using T_From_C = std_array_to_c_arr_t<T_From>;
using T_To_El = remove_all_extents_t<T_To_C>;
using T_From_El = remove_all_extents_t<T_From_C>;
if constexpr (is_pointer_v<T_To_C> || is_pointer_v<T_From_C>) {
if constexpr (Direction == adjust_type_direction::NO_CHANGE) {
static_assert(is_pointer_v<T_To_C> && is_pointer_v<T_From_C> && sizeof(T_To_C) == sizeof(T_From_C));
to = from;
// Structs implement their own convert_type by specializing this class // Have to do this via a class, as functions can't be partially specialized template<typename T_Sbx,
adjust_type_direction Direction,
adjust_type_context Context,
typename T_To,
typename T_From> class convert_type_class; // The specialization implements the following // { // static inline void run(T_To& to, // const T_From& from, // const void* example_unsandboxed_ptr); // }
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.