.. _program_listing_file__tmp_ws_src_rmf_utils_rmf_utils_include_rmf_utils_impl_ptr.hpp: Program Listing for File impl_ptr.hpp ===================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/rmf_utils/rmf_utils/include/rmf_utils/impl_ptr.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /* * Copyright (C) 2019 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef RMF_UTILS__IMPL_PTR_HPP #define RMF_UTILS__IMPL_PTR_HPP #include #include #include // These utilities were derived from https://github.com/oliora/samples/blob/master/spimpl.h // Which uses the following boost license: /* Copyright (c) 2015 Andrey Upadyshev (oliora@gmail.com) Distributed under the Boost Software License, Version 1.0. See http://www.boost.org/LICENSE_1_0.txt */ namespace rmf_utils { namespace details { //============================================================================== template T* default_copy(const T* original) { static_assert(sizeof(T) > 0 && !std::is_void::value, "default_copy cannot copy an incomplete type"); return new T(*original); } //============================================================================== template void default_delete(T* ptr) { static_assert(sizeof(T) > 0 && !std::is_void::value, "default_delete cannot delete an incomplete type"); delete ptr; } //============================================================================== template using default_deleter_t = void (*)(T*); //============================================================================== template using default_copier_t = T* (*)(const T*); template> struct is_default_manageable : public std::integral_constant>::value && std::is_same>::value > {}; } // namespace details //============================================================================== template> class unique_impl_ptr { protected: static_assert( !std::is_array::value, "unique_impl_ptr specialization for arrays is not implemented"); struct dummy_t_ {int dummy__;}; public: using pointer = T*; using const_pointer = typename std::add_const::type*; using reference = T&; using const_reference = typename std::add_const::type&; using element_type = T; using deleter_type = typename std::decay::type; using unique_ptr_type = std::unique_ptr; using is_default_manageable = details::is_default_manageable; constexpr unique_impl_ptr() noexcept : ptr_(nullptr, deleter_type{}) {} constexpr unique_impl_ptr(std::nullptr_t) noexcept : unique_impl_ptr() {} template unique_impl_ptr(pointer p, D&& d, typename std::enable_if< std::is_convertible::value, dummy_t_ >::type = dummy_t_()) noexcept : ptr_(std::move(p), std::forward(d)) {} template unique_impl_ptr(U* u, typename std::enable_if< std::is_convertible::value && is_default_manageable::value, dummy_t_ >::type = dummy_t_()) noexcept : unique_impl_ptr(u, &details::default_delete, &details::default_copy) { } unique_impl_ptr(unique_impl_ptr&& r) noexcept = default; template unique_impl_ptr(std::unique_ptr&& u, typename std::enable_if< std::is_convertible::value && is_default_manageable::value, dummy_t_ >::type = dummy_t_()) noexcept : ptr_(u.release(), &details::default_delete) {} template unique_impl_ptr(std::unique_ptr&& u, typename std::enable_if< std::is_convertible::value && std::is_convertible::value, dummy_t_ >::type = dummy_t_()) noexcept : ptr_(std::move(u)) {} template unique_impl_ptr(unique_impl_ptr&& u, typename std::enable_if< std::is_convertible::value && std::is_convertible::value, dummy_t_ >::type = dummy_t_()) noexcept : ptr_(std::move(u.ptr_)) {} unique_impl_ptr(const unique_impl_ptr&) = delete; unique_impl_ptr& operator=(unique_impl_ptr&& r) noexcept = default; template typename std::enable_if< std::is_convertible::value && is_default_manageable::value, unique_impl_ptr& >::type operator=(std::unique_ptr&& u) noexcept { return operator=(unique_impl_ptr(std::move(u))); } reference operator=(const unique_impl_ptr&) = delete; reference operator*() { return *ptr_; } const_reference operator*() const { return *ptr_; } pointer operator->() noexcept { return get(); } const_pointer operator->() const noexcept { return get(); } pointer get() noexcept { return ptr_.get(); } const_pointer get() const noexcept { return ptr_.get(); } void swap(unique_impl_ptr& u) noexcept { using std::swap; ptr_.swap(u.ptr_); } pointer release() noexcept { return ptr_.release(); } unique_ptr_type release_unique() noexcept { return std::move(ptr_); } explicit operator bool() const noexcept { return static_cast(ptr_); } typename std::remove_reference::type& get_deleter() noexcept { return ptr_.get_deleter(); } const typename std::remove_reference::type& get_deleter() const noexcept { return ptr_.get_deleter(); } protected: unique_ptr_type ptr_; }; template inline void swap(unique_impl_ptr& l, unique_impl_ptr& r) noexcept { l.swap(r); } template inline bool operator==(const unique_impl_ptr& l, const unique_impl_ptr& r) { return l.get() == r.get(); } template inline bool operator!=(const unique_impl_ptr& l, const unique_impl_ptr& r) { return !(l == r); } template inline bool operator<(const unique_impl_ptr& l, const unique_impl_ptr& r) { using P1 = typename unique_impl_ptr::pointer; using P2 = typename unique_impl_ptr::pointer; using CT = typename std::common_type::type; return std::less()(l.get(), r.get()); } template inline bool operator>(const unique_impl_ptr& l, const unique_impl_ptr& r) { return r < l; } template inline bool operator<=(const unique_impl_ptr& l, const unique_impl_ptr& r) { return !(r < l); } template inline bool operator>=(const unique_impl_ptr& l, const unique_impl_ptr& r) { return !(l < r); } template inline bool operator==(const unique_impl_ptr& p, std::nullptr_t) noexcept { return !p; } template inline bool operator==(std::nullptr_t, const unique_impl_ptr& p) noexcept { return !p; } template inline bool operator!=(const unique_impl_ptr& p, std::nullptr_t) noexcept { return static_cast(p); } template inline bool operator!=(std::nullptr_t, const unique_impl_ptr& p) noexcept { return static_cast(p); } template inline bool operator<(const unique_impl_ptr& l, std::nullptr_t) { using P = typename unique_impl_ptr::pointer; return std::less

()(l.get(), nullptr); } template inline bool operator<(std::nullptr_t, const unique_impl_ptr& p) { using P = typename unique_impl_ptr::pointer; return std::less

()(nullptr, p.get()); } template inline bool operator>(const unique_impl_ptr& p, std::nullptr_t) { return nullptr < p; } template inline bool operator>(std::nullptr_t, const unique_impl_ptr& p) { return p < nullptr; } template inline bool operator<=(const unique_impl_ptr& p, std::nullptr_t) { return !(nullptr < p); } template inline bool operator<=(std::nullptr_t, const unique_impl_ptr& p) { return !(p < nullptr); } template inline bool operator>=(const unique_impl_ptr& p, std::nullptr_t) { return !(p < nullptr); } template inline bool operator>=(std::nullptr_t, const unique_impl_ptr& p) { return !(nullptr < p); } template inline unique_impl_ptr make_unique_impl(Args&& ... args) { return unique_impl_ptr(new T(std::forward( args)...), &details::default_delete); } // Helpers to manage unique impl, stored in std::unique_ptr template, class Copier = details::default_copier_t> class impl_ptr : public unique_impl_ptr { using base_type = unique_impl_ptr; using dummy_t_ = typename base_type::dummy_t_; public: using pointer = typename base_type::pointer; using const_pointer = typename base_type::const_pointer; using reference = typename base_type::reference; using const_reference = typename base_type::const_reference; using element_type = typename base_type::element_type; using deleter_type = typename base_type::deleter_type; using unique_ptr_type = typename base_type::unique_ptr_type; using copier_type = typename std::decay::type; using is_default_manageable = details::is_default_manageable; constexpr impl_ptr() noexcept : base_type(nullptr, deleter_type{}), copier_(copier_type{}) {} constexpr impl_ptr(std::nullptr_t) noexcept : impl_ptr() {} template impl_ptr(pointer p, D&& d, C&& c, typename std::enable_if< std::is_convertible::value && std::is_convertible::value, typename base_type::dummy_t_ >::type = typename base_type::dummy_t_()) noexcept : base_type(std::move(p), std::forward(d)), copier_(std::forward(c)) {} template impl_ptr(U* u, typename std::enable_if< std::is_convertible::value && is_default_manageable::value, dummy_t_ >::type = dummy_t_()) noexcept : impl_ptr(u, &details::default_delete, &details::default_copy) {} impl_ptr(const impl_ptr& r) : impl_ptr(r.clone()) {} impl_ptr(impl_ptr&& r) noexcept = default; template impl_ptr(std::unique_ptr&& u, typename std::enable_if< std::is_convertible::value && is_default_manageable::value, dummy_t_ >::type = dummy_t_()) noexcept : base_type(u.release(), &details::default_delete) {} template impl_ptr(std::unique_ptr&& u, C&& c, typename std::enable_if< std::is_convertible::value && std::is_convertible::value, dummy_t_ >::type = dummy_t_()) noexcept : base_type(std::move(u)), copier_(std::forward(c)) {} template impl_ptr(impl_ptr&& u, typename std::enable_if< std::is_convertible::value && std::is_convertible::value, dummy_t_ >::type = dummy_t_()) noexcept : base_type(std::move(u.ptr_)), copier_(std::move(u.copier_)) {} impl_ptr& operator=(const impl_ptr& r) { if (this == &r) return *this; return operator=(r.clone()); } impl_ptr& operator=(impl_ptr&& r) noexcept = default; template typename std::enable_if< std::is_convertible::value && std::is_convertible::value && std::is_convertible::value, impl_ptr& >::type operator=(const impl_ptr& u) { return operator=(u.clone()); } // template typename std::enable_if< std::is_convertible::value && is_default_manageable::value, impl_ptr& >::type operator=(std::unique_ptr&& u) noexcept { return operator=(impl_ptr(std::move(u))); } template typename std::enable_if< std::is_convertible::value && std::is_convertible::value && std::is_convertible::value, impl_ptr& >::type operator=(impl_ptr&& u) noexcept { base_type::ptr_ = std::move(u.ptr_); copier_ = std::move(u.copier_); return *this; } void swap(impl_ptr& u) noexcept { using std::swap; base_type::ptr_.swap(u.ptr_); swap(copier_, u.copier_); } impl_ptr clone() const { return impl_ptr( base_type::ptr_ ? copier_(base_type::ptr_.get()) : nullptr, base_type::ptr_.get_deleter(), copier_); } const typename std::remove_reference::type& get_copier() const noexcept { return copier_; } typename std::remove_reference::type& get_copier() noexcept { return copier_; } private: copier_type copier_; }; template inline impl_ptr make_impl(Args&& ... args) { return impl_ptr(new T(std::forward( args)...), &details::default_delete, &details::default_copy); } template impl_ptr make_derived_impl(Args&& ... args) { return impl_ptr( new D(std::forward(args)...), [](U* ptr) -> void { delete static_cast(ptr); }, [](const U* ptr) -> U* { return new D(*static_cast(ptr)); }); } template inline void swap(impl_ptr& l, impl_ptr& r) noexcept { l.swap(r); } } // namespace rmf_utils namespace std { template struct hash> { using argument_type = rmf_utils::unique_impl_ptr; using result_type = size_t; result_type operator()(const argument_type& p) const noexcept { return hash()(p.get()); } }; template struct hash> { using argument_type = rmf_utils::impl_ptr; using result_type = size_t; result_type operator()(const argument_type& p) const noexcept { return hash()(p.get()); } }; } // namespace std #endif // RMF_UTILS__IMPL_PTR_HPP