From 3fadda314ad3b1fd0ba16db83476a9d5a7b58d78 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Tue, 21 Feb 2012 21:02:58 +0000 Subject: [PATCH] Modernize relational operators for shared_ptr and unique_ptr. This includes adding support for nullptr, and using less. Fixes http://llvm.org/bugs/show_bug.cgi?id=12056. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@151084 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__functional_base | 7 + include/functional | 7 +- include/memory | 229 +++++++++++++++++- .../unique.ptr.special/cmp_nullptr.pass.cpp | 71 ++++++ .../cmp_nullptr.pass.cpp | 71 ++++++ 5 files changed, 377 insertions(+), 8 deletions(-) create mode 100644 test/utilities/memory/unique.ptr/unique.ptr.special/cmp_nullptr.pass.cpp create mode 100644 test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp diff --git a/include/__functional_base b/include/__functional_base index ed7d21b5..63aa41d5 100644 --- a/include/__functional_base +++ b/include/__functional_base @@ -50,6 +50,13 @@ public: static const bool value = sizeof(__test<_Tp>(0)) == 1; }; +template +struct _LIBCPP_VISIBLE less : binary_function<_Tp, _Tp, bool> +{ + _LIBCPP_INLINE_VISIBILITY bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x < __y;} +}; + #ifdef _LIBCPP_HAS_NO_VARIADICS #include <__functional_base_03> diff --git a/include/functional b/include/functional index ee0424d0..8f912fb0 100644 --- a/include/functional +++ b/include/functional @@ -536,12 +536,7 @@ struct _LIBCPP_VISIBLE greater : binary_function<_Tp, _Tp, bool> {return __x > __y;} }; -template -struct _LIBCPP_VISIBLE less : binary_function<_Tp, _Tp, bool> -{ - _LIBCPP_INLINE_VISIBILITY bool operator()(const _Tp& __x, const _Tp& __y) const - {return __x < __y;} -}; +// less in <__functional_base> template struct _LIBCPP_VISIBLE greater_equal : binary_function<_Tp, _Tp, bool> diff --git a/include/memory b/include/memory index e841b2cf..e3dd467b 100644 --- a/include/memory +++ b/include/memory @@ -2964,7 +2964,13 @@ operator!=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {re template inline _LIBCPP_INLINE_VISIBILITY bool -operator< (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __x.get() < __y.get();} +operator< (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) +{ + typedef typename unique_ptr<_T1, _D1>::pointer _P1; + typedef typename unique_ptr<_T2, _D2>::pointer _P2; + typedef typename common_type<_P1, _P2>::type _V; + return less<_V>()(__x.get(), __y.get()); +} template inline _LIBCPP_INLINE_VISIBILITY @@ -2981,6 +2987,104 @@ inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x < __y);} +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + return !__x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + return !__x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + return static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + return static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + typedef typename unique_ptr<_T1, _D1>::pointer _P1; + return less<_P1>()(__x.get(), nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + typedef typename unique_ptr<_T1, _D1>::pointer _P1; + return less<_P1>()(nullptr, __x.get()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + return nullptr < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + return __x < nullptr; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + return !(nullptr < __x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + return !(__x < nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t) +{ + return !(__x < nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) +{ + return !(nullptr < __x); +} + template struct hash; // We use murmur2 when size_t is 32 bits, and cityhash64 when size_t @@ -4620,7 +4724,128 @@ inline _LIBCPP_INLINE_VISIBILITY bool operator<(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT { - return __x.get() < __y.get(); + typedef typename common_type<_Tp*, _Up*>::type _V; + return less<_V>()(__x.get(), __y.get()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT +{ + return __y < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT +{ + return !(__y < __x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT +{ + return !(__x < __y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return !__x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return !__x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return less<_Tp*>()(__x.get(), nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return less<_Tp*>()(nullptr, __x.get()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return nullptr < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return __x < nullptr; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return !(nullptr < __x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return !(__x < nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT +{ + return !(__x < nullptr); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT +{ + return !(nullptr < __x); } template diff --git a/test/utilities/memory/unique.ptr/unique.ptr.special/cmp_nullptr.pass.cpp b/test/utilities/memory/unique.ptr/unique.ptr.special/cmp_nullptr.pass.cpp new file mode 100644 index 00000000..deb615ec --- /dev/null +++ b/test/utilities/memory/unique.ptr/unique.ptr.special/cmp_nullptr.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// shared_ptr + +// template +// bool operator==(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator==(nullptr_t, const unique_ptr& y) noexcept; +// template +// bool operator!=(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator!=(nullptr_t, const unique_ptr& y) noexcept; +// template +// bool operator<(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator<(nullptr_t, const unique_ptr& y) noexcept; +// template +// bool operator<=(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator<=(nullptr_t, const unique_ptr& y) noexcept; +// template +// bool operator>(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator>(nullptr_t, const unique_ptr& y) noexcept; +// template +// bool operator>=(const unique_ptr& x, nullptr_t) noexcept; +// template +// bool operator>=(nullptr_t, const unique_ptr& y) noexcept; + +#include +#include + +void do_nothing(int*) {} + +int main() +{ + int* ptr1(new int); + int* ptr2(new int); + const std::unique_ptr p1(new int(1)); + assert(!(p1 == nullptr)); + assert(!(nullptr == p1)); + assert(!(p1 < nullptr)); + assert( (nullptr < p1)); + assert(!(p1 <= nullptr)); + assert( (nullptr <= p1)); + assert( (p1 > nullptr)); + assert(!(nullptr > p1)); + assert( (p1 >= nullptr)); + assert(!(nullptr >= p1)); + + const std::unique_ptr p2; + assert( (p2 == nullptr)); + assert( (nullptr == p2)); + assert(!(p2 < nullptr)); + assert(!(nullptr < p2)); + assert( (p2 <= nullptr)); + assert( (nullptr <= p2)); + assert(!(p2 > nullptr)); + assert(!(nullptr > p2)); + assert( (p2 >= nullptr)); + assert( (nullptr >= p2)); +} diff --git a/test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp b/test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp new file mode 100644 index 00000000..d8d3113f --- /dev/null +++ b/test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// shared_ptr + +// template +// bool operator==(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator==(nullptr_t, const shared_ptr& y) noexcept; +// template +// bool operator!=(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator!=(nullptr_t, const shared_ptr& y) noexcept; +// template +// bool operator<(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator<(nullptr_t, const shared_ptr& y) noexcept; +// template +// bool operator<=(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator<=(nullptr_t, const shared_ptr& y) noexcept; +// template +// bool operator>(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator>(nullptr_t, const shared_ptr& y) noexcept; +// template +// bool operator>=(const shared_ptr& x, nullptr_t) noexcept; +// template +// bool operator>=(nullptr_t, const shared_ptr& y) noexcept; + +#include +#include + +void do_nothing(int*) {} + +int main() +{ + int* ptr1(new int); + int* ptr2(new int); + const std::shared_ptr p1(new int(1)); + assert(!(p1 == nullptr)); + assert(!(nullptr == p1)); + assert(!(p1 < nullptr)); + assert( (nullptr < p1)); + assert(!(p1 <= nullptr)); + assert( (nullptr <= p1)); + assert( (p1 > nullptr)); + assert(!(nullptr > p1)); + assert( (p1 >= nullptr)); + assert(!(nullptr >= p1)); + + const std::shared_ptr p2; + assert( (p2 == nullptr)); + assert( (nullptr == p2)); + assert(!(p2 < nullptr)); + assert(!(nullptr < p2)); + assert( (p2 <= nullptr)); + assert( (nullptr <= p2)); + assert(!(p2 > nullptr)); + assert(!(nullptr > p2)); + assert( (p2 >= nullptr)); + assert( (nullptr >= p2)); +}