File indexing completed on 2026-08-17 08:52:03
0001
0002
0003
0004
0005
0006 #ifndef BOOST_OPENMETHOD_INTEROP_SHARED_PTR_HPP
0007 #define BOOST_OPENMETHOD_INTEROP_SHARED_PTR_HPP
0008
0009 #include <boost/openmethod/core.hpp>
0010 #include <memory>
0011
0012 namespace boost::openmethod {
0013 namespace detail {
0014
0015 template<class T>
0016 struct shared_ptr_cast_traits {
0017 static_assert(false_t<T>, "cast only allowed to a shared_ptr");
0018 };
0019
0020 template<class T>
0021 struct shared_ptr_cast_traits<std::shared_ptr<T>> {
0022 using virtual_type = T;
0023 };
0024
0025 template<class T>
0026 struct shared_ptr_cast_traits<const std::shared_ptr<T>&> {
0027 using virtual_type = T;
0028 };
0029
0030 template<class T>
0031 struct shared_ptr_cast_traits<std::shared_ptr<T>&&> {
0032 using virtual_type = T;
0033 };
0034
0035 template<typename T, class Registry>
0036 struct validate_method_parameter<std::shared_ptr<T>&, Registry, void>
0037 : std::false_type {
0038 static_assert(
0039 false_t<T>,
0040 "std::shared_ptr cannot be passed by non-const lvalue reference");
0041 };
0042
0043 template<typename T, class Registry>
0044 struct validate_method_parameter<
0045 virtual_ptr<std::shared_ptr<T>, Registry>&, Registry, void>
0046 : std::false_type {
0047 static_assert(
0048 false_t<T>,
0049 "std::shared_ptr cannot be passed by non-const lvalue reference");
0050 };
0051
0052 }
0053
0054
0055
0056
0057
0058 template<typename Class, class Registry>
0059 struct virtual_traits<std::shared_ptr<Class>, Registry> {
0060
0061
0062
0063 template<class Other>
0064 using rebind = std::shared_ptr<Other>;
0065
0066
0067 using virtual_type = std::remove_cv_t<Class>;
0068
0069
0070
0071
0072 static auto peek(const std::shared_ptr<Class>& arg) -> const Class& {
0073 return *arg;
0074 }
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 template<class Derived>
0086 static auto cast(const std::shared_ptr<Class>& obj) -> decltype(auto) {
0087 using namespace boost::openmethod::detail;
0088
0089 if constexpr (requires_dynamic_cast<
0090 Class*, typename Derived::element_type*>) {
0091 return std::dynamic_pointer_cast<
0092 typename shared_ptr_cast_traits<Derived>::virtual_type>(obj);
0093 } else {
0094 return std::static_pointer_cast<
0095 typename shared_ptr_cast_traits<Derived>::virtual_type>(obj);
0096 }
0097 }
0098
0099 #if __cplusplus >= 202002L
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 template<class Derived>
0115 static auto cast(std::shared_ptr<Class>&& obj) -> decltype(auto) {
0116 using namespace boost::openmethod::detail;
0117
0118 if constexpr (requires_dynamic_cast<
0119 Class*, decltype(std::declval<Derived>().get())>) {
0120 return std::dynamic_pointer_cast<
0121 typename shared_ptr_cast_traits<Derived>::virtual_type>(
0122 std::move(obj));
0123 } else {
0124 return std::static_pointer_cast<
0125 typename shared_ptr_cast_traits<Derived>::virtual_type>(
0126 std::move(obj));
0127 }
0128 }
0129 #endif
0130 };
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 template<class Class, class Registry>
0142 struct virtual_traits<const std::shared_ptr<Class>&, Registry> {
0143 public:
0144
0145
0146
0147 template<class Other>
0148 using rebind = std::shared_ptr<Other>;
0149
0150
0151 using virtual_type = std::remove_cv_t<Class>;
0152
0153
0154
0155
0156 static auto peek(const std::shared_ptr<Class>& arg) -> const Class& {
0157 return *arg;
0158 }
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 template<class Other>
0170 static auto cast(const std::shared_ptr<Class>& obj) {
0171 using namespace boost::openmethod::detail;
0172
0173 if constexpr (requires_dynamic_cast<Class*, Other>) {
0174 return std::dynamic_pointer_cast<
0175 typename shared_ptr_cast_traits<Other>::virtual_type>(obj);
0176 } else {
0177 return std::static_pointer_cast<
0178 typename shared_ptr_cast_traits<Other>::virtual_type>(obj);
0179 }
0180 }
0181 };
0182
0183
0184 template<class Class, class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY>
0185 using shared_virtual_ptr = virtual_ptr<std::shared_ptr<Class>, Registry>;
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201 template<
0202 class Class, class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY,
0203 typename... T>
0204 inline auto make_shared_virtual(T&&... args) {
0205 return final_virtual_ptr<Registry>(
0206 std::make_shared<Class>(std::forward<T>(args)...));
0207 }
0208
0209 namespace aliases {
0210 using boost::openmethod::make_shared_virtual;
0211 using boost::openmethod::shared_virtual_ptr;
0212 }
0213
0214 }
0215
0216 #endif