Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix hash_* visualizer issue #2784

Merged
merged 1 commit into from
Jun 25, 2022
Merged

Conversation

fsb4000
Copy link
Contributor

@fsb4000 fsb4000 commented Jun 12, 2022

Fixes #2783

test:

#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
#include <hash_set>
#include <hash_map>
using namespace std;
int main() {
	stdext::hash_set<int> hs = { 1,2,3 };
	stdext::hash_multiset<int> hms = { 1,1,2,3 };
	stdext::hash_map<int, char> hm = { {1, 'a'}, {2,'b'} };
	stdext::hash_multimap<int, char> hmm = { {1, 'a'}, {1, 'c'}, {2,'b'} };
}

изображение

_Traitsobj class:

STL/stl/inc/hash_map

Lines 41 to 110 in e178ea2

class _Hmap_traits : public _Tr { // traits required to make _Hash behave like a map
public:
using key_type = _Kty;
using value_type = pair<const _Kty, _Ty>;
using _Mutable_value_type = pair<_Kty, _Ty>;
using key_compare = _Tr;
using allocator_type = _Alloc;
#if _HAS_CXX17
using node_type =
_STD _Node_handle<_STD _List_node<value_type, typename _STD allocator_traits<_Alloc>::void_pointer>, _Alloc,
_STD _Node_handle_map_base, _Kty, _Ty>;
#endif // _HAS_CXX17
static constexpr bool _Multi = _Mfl;
static constexpr bool _Standard = false;
template <class... _Args>
using _In_place_key_extractor = _STD _In_place_key_extract_map<_Kty, _Args...>;
template <class>
using _Deduce_key = const _Kty&;
using key_equal = _Tr;
_Hmap_traits() = default;
_Hmap_traits(const _Tr& _Traits) noexcept(_STD is_nothrow_copy_constructible_v<_Tr>) : _Tr(_Traits) {}
class value_compare {
public:
using first_argument_type = value_type;
using second_argument_type = value_type;
using result_type = bool;
_NODISCARD bool operator()(const value_type& _Left, const value_type& _Right) const
noexcept(noexcept(_Keycompobj(_Left.first, _Right.first))) {
// test if _Left precedes _Right by comparing just keys
return _Keycompobj(_Left.first, _Right.first);
}
value_compare(const key_compare& _Keycomparg) noexcept(_STD is_nothrow_copy_constructible_v<key_compare>)
: _Keycompobj(_Keycomparg) {}
key_compare _Keycompobj;
};
template <class _Ty1, class _Ty2>
_NODISCARD static const _Kty& _Kfn(const pair<_Ty1, _Ty2>& _Val) noexcept { // extract key from element value
return _Val.first;
}
template <class _Ty1, class _Ty2>
_NODISCARD static const _Ty2& _Nonkfn(const pair<_Ty1, _Ty2>& _Val) noexcept {
// extract non-key from element value
return _Val.second;
}
_NODISCARD float& _Get_max_bucket_size() noexcept {
return _Max_buckets;
}
_NODISCARD const float& _Get_max_bucket_size() const noexcept {
return _Max_buckets;
}
void swap(_Hmap_traits& _Rhs) noexcept(_Is_nothrow_swappable<_Tr>::value) {
_Swap_adl(static_cast<_Tr&>(*this), static_cast<_Tr&>(_Rhs));
_STD swap(_Max_buckets, _Rhs._Max_buckets);
}
float _Max_buckets = 0.0F; // current maximum bucket size
};

_Tr class:

STL/stl/inc/xhash

Lines 59 to 87 in 37b5120

class hash_compare { // traits class for hash containers
public:
enum { // parameters for hash table
bucket_size = 1 // 0 < bucket_size
};
hash_compare() = default;
hash_compare(const _Pr& _Pred) noexcept(_STD is_nothrow_copy_constructible_v<_Pr>) : comp(_Pred) {}
_NODISCARD size_t operator()(const _Kty& _Keyval) const noexcept(noexcept(hash_value(_Keyval))) {
long _Quot = static_cast<long>(hash_value(_Keyval) & LONG_MAX); // TRANSITION, ADL?
ldiv_t _Qrem = _CSTD ldiv(_Quot, 127773);
_Qrem.rem = 16807 * _Qrem.rem - 2836 * _Qrem.quot;
if (_Qrem.rem < 0) {
_Qrem.rem += LONG_MAX;
}
return static_cast<size_t>(_Qrem.rem);
}
_NODISCARD bool operator()(const _Kty& _Keyval1, const _Kty& _Keyval2) const
noexcept(noexcept(comp(_Keyval1, _Keyval2))) {
// test if _Keyval1 ordered before _Keyval2
return comp(_Keyval1, _Keyval2);
}
_Pr comp{}; // the comparator object
};

So we don't visualize [hash_function] and [key_eq], we could visualize [comp] but it doesn't seem useful...

@fsb4000 fsb4000 requested a review from a team as a code owner June 12, 2022 09:37
@StephanTLavavej StephanTLavavej added the visualizer How the VS debugger displays STL types label Jun 12, 2022
<AlternativeType Name="stdext::hash_set&lt;*&gt;" />
<AlternativeType Name="stdext::hash_multiset&lt;*&gt;" />
<DisplayString>{_List}</DisplayString>
<Expand>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No change requested: In theory, comp could be a function pointer worth visualizing. However, it seems likely that it would have to be paired with an ADL-customized hash_value and that seems quite rare (given the poorly-documented nature of this non-Standard extension). I'm okay with this as-is.

@StephanTLavavej StephanTLavavej self-assigned this Jun 25, 2022
@StephanTLavavej
Copy link
Member

I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed.

@StephanTLavavej StephanTLavavej merged commit b23ecba into microsoft:main Jun 25, 2022
@StephanTLavavej
Copy link
Member

Thanks for finding and fixing this visualizer bug - hash_set may be deprecated, but we should still visualize it properly! 🎉 🐈 👁️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
visualizer How the VS debugger displays STL types
Projects
None yet
Development

Successfully merging this pull request may close these issues.

<hash_set>: Natvis errors while debugging
3 participants