summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-05-04 20:13:15 +0200
committerStanislaw Halik <sthalik@misaki.pl>2024-05-05 03:31:20 +0200
commit5c54707ed13c2996f36b99dddb76f017765cec72 (patch)
treeed74b0f349822a58c731823e03aee3661a8d74e7
parent210ee6eab1dcd7b1b2710dc927943d62330ffde3 (diff)
a w
-rw-r--r--compat/borrowed-ptr-fwd.hpp2
-rw-r--r--compat/borrowed-ptr.hpp13
-rw-r--r--test/bptr.cpp31
3 files changed, 38 insertions, 8 deletions
diff --git a/compat/borrowed-ptr-fwd.hpp b/compat/borrowed-ptr-fwd.hpp
index da91502d..465e9bf4 100644
--- a/compat/borrowed-ptr-fwd.hpp
+++ b/compat/borrowed-ptr-fwd.hpp
@@ -44,7 +44,7 @@ public:
T& operator*() const noexcept;
template<typename U> friend class bptr;
- template<typename Tʹ, typename U> friend bptr<U> static_pointer_cast(const bptr<Tʹ>& p) noexcept;
+ template<typename U, typename Tʹ> friend bptr<U> static_pointer_cast(const bptr<Tʹ>& p) noexcept;
};
} // namespace floormat
diff --git a/compat/borrowed-ptr.hpp b/compat/borrowed-ptr.hpp
index 5caa2261..d13d8ee2 100644
--- a/compat/borrowed-ptr.hpp
+++ b/compat/borrowed-ptr.hpp
@@ -28,20 +28,23 @@ concept StaticCastable = requires(From* from) {
namespace floormat {
-template<typename T, typename U>
+template<typename U, typename T>
bptr<U> static_pointer_cast(const bptr<T>& p) noexcept
{
- static_assert(detail_borrowed_ptr::StaticCastable<T, U>);
-
- if (p.blk) [[likely]]
+ // hack to generate better error message
+ if constexpr (detail_borrowed_ptr::StaticCastable<T, U>)
{
- if (auto* ptr = p.blk->_ptr)
+ if (p.blk && p.blk->_ptr) [[likely]]
{
fm_bptr_assert(p.casted_ptr);
auto* ret = static_cast<U*>(p.casted_ptr);
return bptr<U>{DirectInit, ret, p.blk};
}
}
+ else
+ // concepts can't be forward-declared so use static_assert
+ static_assert(detail_borrowed_ptr::StaticCastable<T, U>);
+
return bptr<U>{nullptr};
}
diff --git a/test/bptr.cpp b/test/bptr.cpp
index b8e4bef1..99d6cd2c 100644
--- a/test/bptr.cpp
+++ b/test/bptr.cpp
@@ -4,10 +4,38 @@
namespace floormat {
-namespace { struct Foo {}; struct Bar : Foo {}; struct Baz {}; }
+namespace {
+struct Foo {};
+struct Bar : Foo {};
+struct Baz {};
+} // namespace
+
+// NOLINTBEGIN(*-use-anonymous-namespace)
+
template struct detail_borrowed_ptr::control_block_impl<Foo>;
+template struct detail_borrowed_ptr::control_block_impl<Bar>;
+template struct detail_borrowed_ptr::control_block_impl<Baz>;
+
+template bool operator==(const bptr<Foo>&, const bptr<Foo>&) noexcept;
+template bool operator==(const bptr<Bar>&, const bptr<Bar>&) noexcept;
+template bool operator==(const bptr<Baz>&, const bptr<Baz>&) noexcept;
+
template class bptr<Foo>;
+template class bptr<Bar>;
+template class bptr<Baz>;
+
+template bptr<Foo> static_pointer_cast(const bptr<Foo>&) noexcept;
+template bptr<Bar> static_pointer_cast(const bptr<Bar>&) noexcept;
+template bptr<Baz> static_pointer_cast(const bptr<Baz>&) noexcept;
+
template bptr<Bar> static_pointer_cast(const bptr<Foo>&) noexcept;
+template bptr<Foo> static_pointer_cast(const bptr<Bar>&) noexcept;
+
+//template bptr<Baz> static_pointer_cast(const bptr<Bar>&) noexcept; // must fail
+//template bptr<Foo> static_pointer_cast(const bptr<Baz>&) noexcept; // must fail
+//template bptr<Bar> static_pointer_cast(const bptr<Baz>&) noexcept; // must fail
+
+// NOLINTEND(*-use-anonymous-namespace)
namespace {
@@ -22,5 +50,4 @@ void test_app::test_bptr()
test1();
}
-
} // namespace floormat