Repository: joaquintides/bloom
Pull request #6: added boost_bloom.natvis
Author: login: joaquintides
Created: 2025-05-02T09:45:43Z | Merged: 2025-05-06T14:13:58Z



Diff:
diff --git a/doc/bloom/tutorial.adoc b/doc/bloom/tutorial.adoc
index 977357c..4f5b942 100644
--- a/doc/bloom/tutorial.adoc
+++ b/doc/bloom/tutorial.adoc
@@ -236,3 +236,12 @@ Note that `array()` is a span over `unsigned char`+++s+++ whereas
 capacities are measured in bits, so `array.size()` is
 `capacity() / CHAR_BIT`.
 
+== Debugging
+
+=== Visual Studio Natvis
+
+Add the link:../../extra/boost_bloom.natvis[`boost_bloom.natvis`^] visualizer
+to your project to allow for user-friendly inspection of `boost::bloom::filter`+++s+++.
+
+image::natvis.png[align=center, title="View of a `boost::bloom::filter` with `boost_bloom.natvis`."]
+
diff --git a/doc/img/natvis.png b/doc/img/natvis.png
new file mode 100644
index 0000000..7a6aa83
Binary files /dev/null and b/doc/img/natvis.png differ
diff --git a/extra/boost_bloom.natvis b/extra/boost_bloom.natvis
new file mode 100644
index 0000000..2b38267
--- /dev/null
+++ b/extra/boost_bloom.natvis
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+	
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="false">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)" />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic Name="data" Expression="has_array()?core().ar.buckets:nullptr" />
+	<Intrinsic
+		Name="array_size" 
+		Expression="
+			has_array()?
+				core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size):
+				0"
+	/>
+	<Intrinsic Name="capacity" Expression="array_size()*8" />
+	
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]">
+			*reinterpret_cast&lt;hasher*&gt;(static_cast&lt;hash_base*&gt;(this))
+		</Item>
+		<Item Name="[allocator]">
+			*reinterpret_cast&lt;super::allocator_type*&gt;(static_cast&lt;super::allocator_base*&gt;(this))
+		</Item>
+		<Item Name="[capacity]">
+			capacity()
+		</Item>
+		<Synthetic Name="[array]">
+			<DisplayString>{{ data={(void*)data()} size={array_size()} }}</DisplayString>
+			<Expand>
+				<ArrayItems>
+					<Size>array_size()</Size>
+					<ValuePointer>data()</ValuePointer>
+				</ArrayItems>
+			</Expand>
+		</Synthetic>
+	</Expand>
+</Type>
+
+</AutoVisualizer>
\ No newline at end of file


Reviews:
user: login: k3DW
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-03T21:04:14Z
user: login: joaquintides
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T09:02:03Z
user: login: joaquintides
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T09:04:31Z
user: login: joaquintides
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T09:07:38Z
user: login: joaquintides
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T11:12:35Z
user: login: joaquintides
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-04T11:13:52Z
user: login: k3DW
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-05T04:18:26Z
user: login: joaquintides
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-05T07:43:34Z
user: login: k3DW
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-06T03:25:50Z
user: login: joaquintides
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-06T07:27:10Z
user: login: k3DW
body: Looks great!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-06T13:43:52Z

Review comments:
diff_hunk: @@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="false">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)"  />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic
+		Name="capacity" 
+		Expression="
+			has_array()?
+				(core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size))*8:
+				0"
+	/>
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]" ExcludeView="simple">
path: extra/boost_bloom.natvis
user: login: k3DW
body: You have `ExcludeView="simple"` on every item, meaning that the "simple" view will be empty and therefore meaningless. What would be the point of that? I would recommend removing the `ExcludeView="simple"` attributes altogether, assuming each of these items is equally relevant. Otherwise, I would recommend only putting this attribute on some of the items
created_at: 2025-05-03T20:49:54Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="false">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)"  />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic
+		Name="capacity" 
+		Expression="
+			has_array()?
+				(core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size))*8:
+				0"
+	/>
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]" ExcludeView="simple">
+			*reinterpret_cast&lt;hasher*&gt;(static_cast&lt;hash_base*&gt;(this))
path: extra/boost_bloom.natvis
user: login: k3DW
body: I notice you do `reinterpret_cast<..>(static_cast<..>(..))` as opposed to just a one-step cast. Is this to account for base class offsets?
created_at: 2025-05-03T20:50:54Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="false">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)"  />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic
+		Name="capacity" 
+		Expression="
+			has_array()?
+				(core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size))*8:
+				0"
+	/>
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]" ExcludeView="simple">
+			*reinterpret_cast&lt;hasher*&gt;(static_cast&lt;hash_base*&gt;(this))
+		</Item>
+		<Item Name="[allocator]" ExcludeView="simple">
+			*reinterpret_cast&lt;allocator_type*&gt;(static_cast&lt;super::allocator_base*&gt;(this))
+		</Item>
+		<Item Name="[data]" ExcludeView="simple">
+			has_array()?core().ar.buckets:nullptr
path: extra/boost_bloom.natvis
user: login: k3DW
body: From a user perspective who is not very familiar with the library, what is the relevance of this `[data]`? Would it help a user more to see this in another form, other than `unsigned char*`?
created_at: 2025-05-03T20:55:46Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="false">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)"  />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic
+		Name="capacity" 
+		Expression="
+			has_array()?
+				(core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size))*8:
+				0"
+	/>
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
path: extra/boost_bloom.natvis
user: login: k3DW
body: Is `[capacity]` the most salient property of this type? At a glance, does it give the most relevant information to the user, without needing to expand the dropdown? Why is it in the `DisplayString` instead of being another `Item`? I would also like to see this as an `Item`, regardless of whether it's in the `DisplayString`
created_at: 2025-05-03T20:59:21Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="false">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)"  />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic
+		Name="capacity" 
+		Expression="
+			has_array()?
+				(core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size))*8:
+				0"
+	/>
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]" ExcludeView="simple">
+			*reinterpret_cast&lt;hasher*&gt;(static_cast&lt;hash_base*&gt;(this))
path: extra/boost_bloom.natvis
user: login: joaquintides
body: Yes, exactly, `filter` has two base classes, and the hasher is contained in the second one.
created_at: 2025-05-04T09:02:03Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="false">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)"  />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic
+		Name="capacity" 
+		Expression="
+			has_array()?
+				(core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size))*8:
+				0"
+	/>
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]" ExcludeView="simple">
path: extra/boost_bloom.natvis
user: login: joaquintides
body: 97df326621e86def940994beccc12e230c0ed6d4
created_at: 2025-05-04T09:04:31Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="false">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)"  />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic
+		Name="capacity" 
+		Expression="
+			has_array()?
+				(core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size))*8:
+				0"
+	/>
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]" ExcludeView="simple">
+			*reinterpret_cast&lt;hasher*&gt;(static_cast&lt;hash_base*&gt;(this))
+		</Item>
+		<Item Name="[allocator]" ExcludeView="simple">
+			*reinterpret_cast&lt;allocator_type*&gt;(static_cast&lt;super::allocator_base*&gt;(this))
+		</Item>
+		<Item Name="[data]" ExcludeView="simple">
+			has_array()?core().ar.buckets:nullptr
path: extra/boost_bloom.natvis
user: login: joaquintides
body: `[data]` is just the internal bit array, seen as an array of `unsigned char`s.  This is the memory region the member function `array` returns a pointer to (wrapped in a span object). I don't think I can provide a more meaningful view into this, as a bit array is, well, a bit array.
created_at: 2025-05-04T09:07:38Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="false">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)"  />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic
+		Name="capacity" 
+		Expression="
+			has_array()?
+				(core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size))*8:
+				0"
+	/>
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]" ExcludeView="simple">
+			*reinterpret_cast&lt;hasher*&gt;(static_cast&lt;hash_base*&gt;(this))
+		</Item>
+		<Item Name="[allocator]" ExcludeView="simple">
+			*reinterpret_cast&lt;allocator_type*&gt;(static_cast&lt;super::allocator_base*&gt;(this))
+		</Item>
+		<Item Name="[data]" ExcludeView="simple">
+			has_array()?core().ar.buckets:nullptr
path: extra/boost_bloom.natvis
user: login: joaquintides
body: Well, thanks for challenging me! Learning from your MapHelper view in Boost.Unordered I managed to get this (76bac473e18bb0621d7cd80a15919c4b0bec2f44):

![natvis](https://github.com/user-attachments/assets/10470990-69cf-4670-8b6f-65717998b94a)

created_at: 2025-05-04T11:12:35Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="false">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)"  />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic
+		Name="capacity" 
+		Expression="
+			has_array()?
+				(core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size))*8:
+				0"
+	/>
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
path: extra/boost_bloom.natvis
user: login: joaquintides
body: Yes, it is the most salient property. Also, I'm mimicking what the view for `std::vector` does (it shows just the size in the `DisplayString`). Added [capacity] as an item in 76bac473e18bb0621d7cd80a15919c4b0bec2f44.
created_at: 2025-05-04T11:13:52Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+	
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="true">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)" />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic Name="data" Expression="has_array()?core().ar.buckets:nullptr" />
+	<Intrinsic
+		Name="array_size" 
+		Expression="
+			has_array()?
+				core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size):
+				0"
+	/>
+	<Intrinsic Name="capacity" Expression="array_size()*8" />
+	
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]">
+			*reinterpret_cast&lt;hasher*&gt;(static_cast&lt;hash_base*&gt;(this))
+		</Item>
+		<Item Name="[allocator]">
+			*reinterpret_cast&lt;super::allocator_type*&gt;(static_cast&lt;super::allocator_base*&gt;(this))
+		</Item>
+		<Item Name="[capacity]">
+			capacity()
+		</Item>
+		<Item Name="[array]">
+			*this,view(ArrayView)
path: extra/boost_bloom.natvis
user: login: k3DW
body: When showing the array items, it's more idiomatic Natvis to write it with the `ArrayItems` tag in this expansion directly, rather than as an `Item` that expands to a separate overload of the `Type`. See [these lines of STL.natvis for `std::vector`](https://github.com/microsoft/STL/blob/main/stl/debugger/STL.natvis#L1193-L1205) as an example

Then you could remove the other overload of this `Type` tag on line 42
created_at: 2025-05-05T04:14:52Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+	
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="true">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)" />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic Name="data" Expression="has_array()?core().ar.buckets:nullptr" />
+	<Intrinsic
+		Name="array_size" 
+		Expression="
+			has_array()?
+				core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size):
+				0"
+	/>
+	<Intrinsic Name="capacity" Expression="array_size()*8" />
+	
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]">
+			*reinterpret_cast&lt;hasher*&gt;(static_cast&lt;hash_base*&gt;(this))
+		</Item>
+		<Item Name="[allocator]">
+			*reinterpret_cast&lt;super::allocator_type*&gt;(static_cast&lt;super::allocator_base*&gt;(this))
+		</Item>
+		<Item Name="[capacity]">
+			capacity()
+		</Item>
+		<Item Name="[array]">
+			*this,view(ArrayView)
path: extra/boost_bloom.natvis
user: login: joaquintides
body: I think I like my previous version better:

With `ArrayView`:
![natvis](https://github.com/user-attachments/assets/8f7727c2-9b39-47ad-beec-f6b37e9cfe0b)

Without `ArrayView`:
![imagen](https://github.com/user-attachments/assets/3beba46e-3f3a-44e0-9d99-67fe0c20c5ec)

The second version:

* Expands directly, which I'm not very happy about (the array is very inscrutable as it consists of random bits, so I don't think inspecting it is the thing users will want to do foremost).
* Does not show the size (distinct from capacity, in particular size = capacity/8).
* May give the false impresion that `boost::bloom::filter` has an `operator []`,  which is not the case --it's `boost::bloom::filter::array()` that has it.
created_at: 2025-05-05T07:43:33Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+	
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="true">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)" />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic Name="data" Expression="has_array()?core().ar.buckets:nullptr" />
+	<Intrinsic
+		Name="array_size" 
+		Expression="
+			has_array()?
+				core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size):
+				0"
+	/>
+	<Intrinsic Name="capacity" Expression="array_size()*8" />
+	
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]">
+			*reinterpret_cast&lt;hasher*&gt;(static_cast&lt;hash_base*&gt;(this))
+		</Item>
+		<Item Name="[allocator]">
+			*reinterpret_cast&lt;super::allocator_type*&gt;(static_cast&lt;super::allocator_base*&gt;(this))
+		</Item>
+		<Item Name="[capacity]">
+			capacity()
+		</Item>
+		<Item Name="[array]">
+			*this,view(ArrayView)
path: extra/boost_bloom.natvis
user: login: k3DW
body: Understood. In that case, the idiomatic way to express what you want is through a `Synthetic` element. It is confusing and may lead to buggy usage in the future if you overload the same type you're already in

```xml
<Synthetic Name="[array]">
    <DisplayString>{{ data={(void*)data()} size={array_size()} }}</DisplayString>
    <Expand>
        <ArrayItems>
            <Size>array_size()</Size>
            <ValuePointer>data()</ValuePointer>
        </ArrayItems>
    </Expand>
</Synthetic>
```
created_at: 2025-05-06T03:25:50Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2025 Joaquin M Lopez Munoz.
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+See https://www.boost.org/libs/bloom for library home page. 
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+	
+<Type Name="boost::bloom::filter&lt;*&gt;" Inheritable="true">
+	<Intrinsic Name="core" Expression="*static_cast&lt;super*&gt;(this)" />
+	<Intrinsic Name="has_array" Expression="core().ar.data!=nullptr" />
+	<Intrinsic Name="data" Expression="has_array()?core().ar.buckets:nullptr" />
+	<Intrinsic
+		Name="array_size" 
+		Expression="
+			has_array()?
+				core().hs.rng*super::bucket_size+(super::used_value_size-super::bucket_size):
+				0"
+	/>
+	<Intrinsic Name="capacity" Expression="array_size()*8" />
+	
+	<DisplayString>{{ capacity={capacity()} }}</DisplayString>
+	<Expand>
+		<Item Name="[hash_function]">
+			*reinterpret_cast&lt;hasher*&gt;(static_cast&lt;hash_base*&gt;(this))
+		</Item>
+		<Item Name="[allocator]">
+			*reinterpret_cast&lt;super::allocator_type*&gt;(static_cast&lt;super::allocator_base*&gt;(this))
+		</Item>
+		<Item Name="[capacity]">
+			capacity()
+		</Item>
+		<Item Name="[array]">
+			*this,view(ArrayView)
path: extra/boost_bloom.natvis
user: login: joaquintides
body: Yes, that's it! 60f3908710551e2d8a126a016402b9fbb2088fae:

![natvis](https://github.com/user-attachments/assets/ea85c004-90c6-47b7-998f-e28cba161f89)

created_at: 2025-05-06T07:27:10Z
author_association: MEMBER

PR comments:
user: login: cppalliance-bot
created_at: 2025-05-02T09:51:34Z
body: An automated preview of the documentation is available at [https://6.bloom.prtest3.cppalliance.org/libs/bloom/doc/html/index.html](https://6.bloom.prtest3.cppalliance.org/libs/bloom/doc/html/index.html)
author_association: NONE
user: login: joaquintides
created_at: 2025-05-02T20:15:06Z
body: Hi @k3DW, thanks for reviewing this! In particular, I've got no clue about what attributes `ExcludeView` and `Inheritable` do, and I just merely copied what I saw around.

It'd be nice, if the lib is accepted, to have a GDB pretty-printer, but that's definitely beyond my skills :-)
author_association: MEMBER
user: login: cppalliance-bot
created_at: 2025-05-04T09:11:44Z
body: An automated preview of the documentation is available at [https://6.bloom.prtest3.cppalliance.org/libs/bloom/doc/html/index.html](https://6.bloom.prtest3.cppalliance.org/libs/bloom/doc/html/index.html)
author_association: NONE
user: login: cppalliance-bot
created_at: 2025-05-04T11:16:41Z
body: An automated preview of the documentation is available at [https://6.bloom.prtest3.cppalliance.org/libs/bloom/doc/html/index.html](https://6.bloom.prtest3.cppalliance.org/libs/bloom/doc/html/index.html)
author_association: NONE
user: login: cppalliance-bot
created_at: 2025-05-04T16:11:24Z
body: An automated preview of the documentation is available at [https://6.bloom.prtest3.cppalliance.org/libs/bloom/doc/html/index.html](https://6.bloom.prtest3.cppalliance.org/libs/bloom/doc/html/index.html)
author_association: NONE
user: login: cppalliance-bot
created_at: 2025-05-06T07:36:39Z
body: An automated preview of the documentation is available at [https://6.bloom.prtest3.cppalliance.org/libs/bloom/doc/html/index.html](https://6.bloom.prtest3.cppalliance.org/libs/bloom/doc/html/index.html)
author_association: NONE
user: login: joaquintides
created_at: 2025-05-06T14:13:51Z
body: > Looks great!

Thanks for your review! It has greatly improved the original PR.
author_association: MEMBER