// // ip_constexpr_test.cpp // // Copyright 2025 Mathias Stearn // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt // #include #ifndef BOOST_SP_NO_CXX20_CONSTEXPR struct dummy { // no-ops, so safe on pointers to static constexpr variables friend constexpr void intrusive_ptr_add_ref(const dummy *) {} friend constexpr void intrusive_ptr_release(const dummy *) {} }; static constexpr dummy d; struct subdummy : dummy {}; // Test that basic operations work at compile time. static_assert(bool(boost::intrusive_ptr(&d))); static_assert(!bool(boost::intrusive_ptr(nullptr))); static_assert(!bool(boost::intrusive_ptr())); static_assert(!bool(boost::intrusive_ptr(boost::intrusive_ptr()))); static_assert(&*boost::intrusive_ptr(&d) == &d); static_assert(boost::intrusive_ptr(&d).operator->() == &d); static_assert(boost::intrusive_ptr() == nullptr); static_assert(boost::intrusive_ptr() == boost::intrusive_ptr(nullptr)); static_assert(boost::intrusive_ptr() != boost::intrusive_ptr(&d)); static_assert(boost::intrusive_ptr(&d) != nullptr); static_assert(boost::intrusive_ptr(&d) == boost::intrusive_ptr(&d)); static_assert(boost::intrusive_ptr(&d) == boost::intrusive_ptr(&d).get()); static_assert(boost::intrusive_ptr(&d) == boost::intrusive_ptr(&d).detach()); static_assert(!(boost::intrusive_ptr(&d) < boost::intrusive_ptr(&d))); static_assert(boost::get_pointer(boost::intrusive_ptr(&d)) == &d); static_assert(boost::static_pointer_cast( boost::intrusive_ptr(&d)) == &d); static_assert(boost::const_pointer_cast( boost::intrusive_ptr(&d)) == &d); static_assert(boost::dynamic_pointer_cast( boost::intrusive_ptr(&d)) == &d); constexpr auto lvalue = boost::intrusive_ptr(&d); constexpr auto lvalue_convertible = boost::intrusive_ptr(); static_assert(boost::intrusive_ptr(lvalue) == &d); static_assert(!boost::intrusive_ptr(lvalue_convertible)); static_assert(boost::static_pointer_cast(lvalue) == &d); static_assert(boost::const_pointer_cast(lvalue) == &d); static_assert(boost::dynamic_pointer_cast(lvalue) == &d); // Works in places that static_assert doesn't, like expressions with // non-constexpr variables in constexpr functions. template constexpr void semi_static_assert(T b) { if (!b) throw "assertion failed"; // Not constexpr so fails compile. } constexpr bool test_swap() { auto p1 = boost::intrusive_ptr(&d); auto p2 = boost::intrusive_ptr(); swap(p1, p2); semi_static_assert(!p1 && p2); p1.swap(p2); semi_static_assert(p1 && !p2); return true; } static_assert(test_swap()); constexpr bool test_reset_assign() { // Test assignments resulting in nullptr { auto p1 = boost::intrusive_ptr(&d); p1.reset(); semi_static_assert(!p1); } { auto p1 = boost::intrusive_ptr(&d); p1.reset(nullptr); semi_static_assert(!p1); } { auto p1 = boost::intrusive_ptr(&d); p1 = nullptr; semi_static_assert(!p1); } { auto p1 = boost::intrusive_ptr(&d); p1 = boost::intrusive_ptr(); semi_static_assert(!p1); } { auto p1 = boost::intrusive_ptr(&d); p1 = boost::intrusive_ptr(); semi_static_assert(!p1); } { auto p1 = boost::intrusive_ptr(&d); p1 = lvalue_convertible; semi_static_assert(!p1); } // Test assignments resulting in &d { auto p1 = boost::intrusive_ptr(); p1.reset(&d); semi_static_assert(p1 == &d); } { auto p1 = boost::intrusive_ptr(); p1.reset(&d, true); semi_static_assert(p1 == &d); } { auto p1 = boost::intrusive_ptr(); p1 = boost::intrusive_ptr(&d); semi_static_assert(p1 == &d); } { auto p1 = boost::intrusive_ptr(); p1 = lvalue; semi_static_assert(p1 == &d); } { auto p1 = boost::intrusive_ptr(); p1 = &d; semi_static_assert(p1 == &d); } return true; } static_assert(test_reset_assign()); #endif