File tree Expand file tree Collapse file tree 8 files changed +82
-2
lines changed Expand file tree Collapse file tree 8 files changed +82
-2
lines changed Original file line number Diff line number Diff line change 88#include < safe/int.hpp>
99#include < safe/match.hpp>
1010#include < safe/object.hpp>
11+ #include < safe/safe_cast.hpp>
1112#include < safe/value.hpp>
1213#include < safe/var.hpp>
Original file line number Diff line number Diff line change @@ -37,12 +37,12 @@ template <typename T> struct unsafe_cast_ferry {
3737
3838template <typename T>
3939 requires (safe::Var<T>)
40- [[nodiscard]] constexpr auto unsafe_cast(auto const &src) {
40+ [[nodiscard]] SAFE_INLINE constexpr auto unsafe_cast(auto const &src) {
4141 return T{safe::unsafe_cast_ferry{src}};
4242}
4343
4444template <typename T>
4545 requires (!safe::Var<T>)
46- [[nodiscard]] constexpr auto unsafe_cast(auto const &src) {
46+ [[nodiscard]] SAFE_INLINE constexpr auto unsafe_cast(auto const &src) {
4747 return src;
4848}
Original file line number Diff line number Diff line change 1+ #pragma once
2+
3+ #include < safe/detail/concepts.hpp>
4+ #include < safe/detail/fwd.hpp>
5+ #include < safe/var.hpp>
6+
7+ #include < concepts>
8+
9+ template <typename To, safe::Var From>
10+ requires (std::is_convertible_v<typename From::value_type, To>)
11+ [[nodiscard]] SAFE_INLINE constexpr To safe_cast(From const &src) {
12+ static_assert (safe::detail::integral_type<To>::requirement >=
13+ From::requirement,
14+ " The safe value must fit within the target value type." );
15+
16+ return static_cast <To>(src.unsafe_value_ );
17+ }
Original file line number Diff line number Diff line change 11add_subdirectory (array)
22add_subdirectory (var)
3+ add_subdirectory (safe_cast)
34
45function (add_test_suites)
56 foreach (test_file ${ARGN} )
@@ -34,6 +35,7 @@ add_test_suites(
3435 var.cpp
3536 match.cpp
3637 array.cpp
38+ safe_cast.cpp
3739 dsl/add.cpp
3840 dsl/divide.cpp
3941 dsl/intersection.cpp
Original file line number Diff line number Diff line change 1+ #include " gmock/gmock.h"
2+ #include " gtest/gtest.h"
3+
4+ #include < cstdint>
5+ #include < type_traits>
6+
7+ #include < safe.hpp>
8+
9+ using ::testing::_;
10+ using ::testing::InSequence;
11+ using ::testing::Return;
12+
13+ using namespace safe ::interval_types;
14+ using namespace safe ::int_types;
15+ using namespace safe ::literals;
16+
17+ TEST (safe_cast_test, cast_same_type) {
18+ auto v = safe_cast<std::int32_t >(42_s32);
19+ EXPECT_EQ (v, 42 );
20+ static_assert (std::is_same_v<std::int32_t , decltype (v)>);
21+ }
22+
23+ TEST (safe_cast_test, cast_narrower_type) {
24+ auto v = safe_cast<std::uint8_t >(42_s32);
25+ EXPECT_EQ (v, 42 );
26+ static_assert (std::is_same_v<std::uint8_t , decltype (v)>);
27+ }
28+
29+ TEST (safe_cast_test, cast_different_sign) {
30+ auto v = safe_cast<std::uint32_t >(99_s32);
31+ EXPECT_EQ (v, 99 );
32+ static_assert (std::is_same_v<std::uint32_t , decltype (v)>);
33+ }
Original file line number Diff line number Diff line change 1+ function (add_fail_tests)
2+ foreach (name ${ARGN} )
3+ add_compile_fail_test("${name} .cpp" LIBRARIES safe_arithmetic)
4+ endforeach ()
5+ endfunction ()
6+
7+ add_fail_tests(
8+ incompatible_sign_cast
9+ incompatible_range_cast)
Original file line number Diff line number Diff line change 1+ #include < cstdint>
2+
3+ #include < safe.hpp>
4+
5+ using namespace safe ::interval_types;
6+ using namespace safe ::int_types;
7+ using namespace safe ::literals;
8+
9+ auto main () -> int { auto v = safe_cast<std::uint8_t >(420_u32); }
Original file line number Diff line number Diff line change 1+ #include < cstdint>
2+
3+ #include < safe.hpp>
4+
5+ using namespace safe ::interval_types;
6+ using namespace safe ::int_types;
7+ using namespace safe ::literals;
8+
9+ auto main () -> int { auto v = safe_cast<std::uint32_t >(-99_s32); }
You can’t perform that action at this time.
0 commit comments