// // Tests for // template // bounded_ptr(bounded_ptr const& other); // #include #include #include #include #include #include "test_utils.h" #define _assert(...) T_ASSERT_TRUE((__VA_ARGS__), # __VA_ARGS__) struct Base { int i; }; struct Derived : Base { }; struct Base1 { int i; }; struct Base2 { long l; }; struct DerivedMultiple : Base1, Base2 { DerivedMultiple(int i) : Base1{i}, Base2{i + 10} { } }; struct Unrelated { }; struct dummy_policy1 { static constexpr void trap(char const*) { } }; struct dummy_policy2 { static constexpr void trap(char const*) { } }; template static void tests() { std::array array = {Stored{0}, Stored{1}, Stored{2}, Stored{3}, Stored{4}}; Stored* const ptr = array.begin() + 2; { test_bounded_ptr const from(ptr, array.begin(), array.end()); test_bounded_ptr to = from; // conversion (implicit) _assert(to.discard_bounds() == static_cast(ptr)); } { test_bounded_ptr const from(ptr, array.begin(), array.end()); test_bounded_ptr to(from); // conversion (explicit) _assert(to.discard_bounds() == static_cast(ptr)); } { test_bounded_ptr const from(ptr, array.begin(), array.end()); test_bounded_ptr to{from}; // conversion (explicit) _assert(to.discard_bounds() == static_cast(ptr)); } { test_bounded_ptr const from(ptr, array.begin(), array.end()); test_bounded_ptr to = static_cast >(from); // conversion (explicit) _assert(to.discard_bounds() == static_cast(ptr)); } // Test converting from a null pointer { test_bounded_ptr from = nullptr; test_bounded_ptr to = from; // conversion (implicit) _assert(to.unsafe_discard_bounds() == nullptr); } // Test with different policies { libkern::bounded_ptr from(ptr, array.begin(), array.end()); libkern::bounded_ptr to = from; // conversion (implicit) _assert(to.discard_bounds() == static_cast(ptr)); } // T{0} T{1} T{2} T{3} T{4} // ^ ^ ^ // | | | // from begin end { test_bounded_ptr const from(array.begin(), array.begin() + 1, array.end()); test_bounded_ptr to(from); _assert(to.unsafe_discard_bounds() == static_cast(array.begin())); } } T_DECL(ctor_convert, "bounded_ptr.ctor.convert", T_META_TAG_VM_PREFERRED) { tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); tests(); // Make sure downcasts are disabled static_assert(!std::is_convertible_v, /*to*/ test_bounded_ptr >); static_assert(!std::is_convertible_v, /*to*/ test_bounded_ptr >); static_assert(!std::is_convertible_v, /*to*/ test_bounded_ptr >); static_assert(!std::is_convertible_v, /*to*/ test_bounded_ptr >); // Make sure const-casting away doesn't work static_assert(!std::is_convertible_v, /*to*/ test_bounded_ptr >); // Make sure casting to unrelated types doesn't work implicitly static_assert(!std::is_convertible_v, /*to*/ test_bounded_ptr >); static_assert(!std::is_convertible_v, /*to*/ test_bounded_ptr >); static_assert(!std::is_convertible_v, /*to*/ test_bounded_ptr >); // Make sure even explicit conversion to unrelated types doesn't work static_assert(!std::is_constructible_v, /*from*/ test_bounded_ptr >); static_assert(!std::is_constructible_v, /*from*/ test_bounded_ptr >); static_assert(!std::is_constructible_v, /*from*/ test_bounded_ptr >); // Make sure construction from a raw pointer doesn't work static_assert(!std::is_constructible_v, /*from*/ Derived*>); }