Skip to content

Commit 822d5d0

Browse files
committed
Support for std::hash
1 parent 8ef222a commit 822d5d0

File tree

6 files changed

+37
-5
lines changed

6 files changed

+37
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
77

88
### Added
99
- Support for `std::format` (if available). Instances of `intrusive_shared_ptr` can be passed to `std::format`
10-
and will be printed like a `void *`.
10+
and will be printed like a `void *`.
11+
- Support for `std::hash<intrusive_shared_ptr>`.
1112
- `get_inout_param()` method. This provides the same functionality as `std::inout_ptr` but is available for pre-C++23 compilation.
1213

1314
### Changed

doc/intrusive_shared_ptr.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ using traits_type = Traits;
8585
any traits as well as raw pointers and nullptr.
8686
- Comparisons: `<`, `<=`, `>=`, `>`. All `noexcept`. On C++20 these are replaced by `<=>`. Work between `intrusive_shared_ptr` of compatible types and
8787
any traits as well as raw pointers.
88-
- Namespace method: `template<class Char> friend std::basic_ostream<Char> & operator<<(std::basic_ostream<Char> & str, const intrusive_shared_ptr<T, Traits> & ptr)` (ADL only) outputs the stored pointer value to a stream
88+
- Hash code: `constexpr size_t hash_value(const intrusive_shared_ptr<T, Traits> & ptr) noexcept`.
89+
- Stream output: `template<class Char> friend std::basic_ostream<Char> & operator<<(std::basic_ostream<Char> & str, const intrusive_shared_ptr<T, Traits> & ptr)` (ADL only) outputs the stored pointer value to a stream
8990

9091
- `Dest intrusive_const_cast<Dest>(intrusive_shared_ptr src) noexcept`. Performs an equivalent of `const_cast` on passed argument. The destination type needs to be a valid `intrusive_shared_ptr` type whose underlying type is convertible from source's via `const_cast`.
9192
- `Dest intrusive_static_cast<Dest>(intrusive_shared_ptr src) noexcept`. Performs an equivalent of `static_cast` on passed argument. The destination type needs to be a valid `intrusive_shared_ptr` type whose underlying type is convertible from source's via `static_cast`.
@@ -96,6 +97,7 @@ using traits_type = Traits;
9697
- `std::out_ptr_t<intrusive_shared_ptr>` and `std::inout_ptr_t<intrusive_shared_ptr>`. Provide support for using
9798
`std::out_ptr` and `std::inout_ptr` with `intrusive_shared_ptr`
9899
- `std::formatter<intrusive_shared_ptr>`. Provides support for using `std::format` with `intrusive_shared_ptr` instances
100+
- `std::hash<intrusive_shared_ptr>`
99101

100102
## Class std::atomic&lt;isptr::intrusive_shared_ptr&gt;
101103

inc/intrusive_shared_ptr/common.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
#endif
3838

3939
#if __cpp_lib_out_ptr >= 202106L
40-
41-
#include <memory>
4240

4341
#define ISPTR_SUPPORT_OUT_PTR 1
4442

inc/intrusive_shared_ptr/intrusive_shared_ptr.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <type_traits>
1515
#include <ostream>
1616
#include <atomic>
17+
#include <memory>
1718

1819

1920
namespace isptr
@@ -334,6 +335,9 @@ namespace isptr
334335
template<class Char>
335336
friend std::basic_ostream<Char> & operator<<(std::basic_ostream<Char> & str, const intrusive_shared_ptr<T, Traits> & ptr)
336337
{ return str << ptr.m_p; }
338+
339+
friend constexpr size_t hash_value(const intrusive_shared_ptr<T, Traits> & ptr) noexcept
340+
{ return std::hash<T *>()(ptr.m_p); }
337341

338342
private:
339343
constexpr intrusive_shared_ptr(T * ptr) noexcept :
@@ -557,6 +561,14 @@ namespace std
557561
{ return formatter<void *, CharT>::format(ptr.get(), ctx); }
558562
};
559563
#endif
564+
565+
ISPTR_EXPORTED
566+
template<class T, class Traits>
567+
struct hash<::isptr::intrusive_shared_ptr<T, Traits>>
568+
{
569+
constexpr size_t operator()(const ::isptr::intrusive_shared_ptr<T, Traits> & ptr) const noexcept
570+
{ return hash_value(ptr); }
571+
};
560572
}
561573

562574
#undef ISPTR_TRIVIAL_ABI

modules/isptr.cppm

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ export module isptr;
7171
#endif
7272

7373
#if __cpp_lib_out_ptr >= 202106L
74-
7574

7675
#define ISPTR_SUPPORT_OUT_PTR 1
7776

@@ -447,6 +446,9 @@ namespace isptr
447446
template<class Char>
448447
friend std::basic_ostream<Char> & operator<<(std::basic_ostream<Char> & str, const intrusive_shared_ptr<T, Traits> & ptr)
449448
{ return str << ptr.m_p; }
449+
450+
friend constexpr size_t hash_value(const intrusive_shared_ptr<T, Traits> & ptr) noexcept
451+
{ return std::hash<T *>()(ptr.m_p); }
450452

451453
private:
452454
constexpr intrusive_shared_ptr(T * ptr) noexcept :
@@ -670,6 +672,14 @@ namespace std
670672
{ return formatter<void *, CharT>::format(ptr.get(), ctx); }
671673
};
672674
#endif
675+
676+
ISPTR_EXPORTED
677+
template<class T, class Traits>
678+
struct hash<::isptr::intrusive_shared_ptr<T, Traits>>
679+
{
680+
constexpr size_t operator()(const ::isptr::intrusive_shared_ptr<T, Traits> & ptr) const noexcept
681+
{ return hash_value(ptr); }
682+
};
673683
}
674684

675685
#undef ISPTR_TRIVIAL_ABI

test/test_general.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,4 +562,13 @@ TEST_CASE( "Member pointer" ) {
562562
CHECK(x == 1);
563563
}
564564

565+
TEST_CASE( "Hash code" ) {
566+
567+
instrumented_counted<> object;
568+
auto ptr = mock_noref(&object);
569+
570+
CHECK(std::hash<decltype(ptr)>()(ptr) == std::hash<instrumented_counted<> *>()(&object));
571+
CHECK(std::hash<decltype(ptr)>()(ptr) == hash_value(ptr));
572+
}
573+
565574
}

0 commit comments

Comments
 (0)