-
Notifications
You must be signed in to change notification settings - Fork 9
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
Added reference_proxy and bitset_view #13
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A first pass.
{ | ||
public: | ||
|
||
using self_type = reference_proxy<T>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference goes to this_type
but ok
template <class U> | ||
self_type& operator/=(const U&); | ||
|
||
operator const_reference() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be explicit
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This requires that you explicitly cast each time you want to compare the proxy to a value (for instance), which is paricularly ugly (and does not looks naturaly at all to me):
template <class T>
struct array_impl
{
using reference = reference_proxy<std::uint8_t>;
const_reference = const std::uint8_t&;
using size_type = std::size_t;
reference operator[](size_type i);
};
array<std::uint8_t> a = ....;
uint8_t expected = 8u;
// With explicit you need to
using const_reference = array<std::uint8_t>::const_reference;
bool b = (const_reference(a[i]) == expected);
// while without, you can simply write:
bool b = a[i] == expected;
How having this operator implicit can be harmful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How having this operator implicit can be harmful?
See this guideline for the fundations of why it's a very bad idea. It goes in pair with the guideline about conversion operator that must also be explicit. The cases where this would not work as so rare I, so far, never saw a justifyiable example that isn't improved by explicit
.
This requires that you explicitly cast each time you want to compare the proxy to a value (for instance), which is paricularly ugly (and does not looks naturaly at all to me):
That just means that the reference type needs comparison operators with objects of the type being referred to. That conversion is a shortctut that can cause more issues than explicitly stating these operators.
Also note that even like that "ugly" is not a reason to make the code potentially silently incorrect, in particular in a C++ library supposedly trying to make correctness easier than the C api. Worst scenario, static_cast
s are fine and help clarify where are the potential issues related to conversion. They are noisy for a reason after all.
See as example: https://godbolt.org/z/7jxcvjq3Y
I see no reason to make that operator implicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot a test in my example, here is the udpated version (I only added the test): https://godbolt.org/z/TYx7sGezj
#include "sparrow/dynamic_bitset.hpp" | ||
#include "sparrow/data_type.hpp" | ||
|
||
namespace sparrow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add some documentation for each one of these types?
|
||
reference back(); | ||
const_reference back() const; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about begin
and end
? Is this not a range/container?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah they should be, and I want to refactor this hierarchy to be consistent with the dynamic bitset. We can add it in an incoming PR though, to keep this one quite "small" (it is actually already big)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding TODOs for these so that we dont forget in further passes.
template <class T> | ||
void buffer<T>::resize(size_type n, value_type value) | ||
{ | ||
size_type old_size = size(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const
{ | ||
public: | ||
|
||
constexpr explicit data_descriptor(data_type id = data_type::UINT8) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer a separate default constructor which calls the explicit constructor with 1 parameter. That we we dont have an explicit default constructor.
template <class B> | ||
void dynamic_bitset_base<B>::resize(size_type n, value_type b) | ||
{ | ||
size_type old_block_count = m_buffer.size(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another pass.
std::vector<buffer<block_type>> buffers; | ||
std::vector<array_data> child_data; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be used instead?
std::vector<buffer<block_type>> buffers; | |
std::vector<array_data> child_data; | |
buffer<buffer<block_type>> buffers; | |
buffer<array_data> child_data; |
buffer<T>::buffer(size_type size, value_type value) | ||
: base_type{allocate(size), size} | ||
{ | ||
std::fill(data(), data() + size, value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an alternative.
std::fill(data(), data() + size, value); | |
std::fill_n(data(), size, value); |
resize(n); | ||
if (old_size < n) | ||
{ | ||
std::fill(data() + old_size, data() + n, value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, one can use:
std::fill(data() + old_size, data() + n, value); | |
std::fill_n(data() + old_size, n, value); |
CHECK_EQ(b.size(), size1); | ||
CHECK_EQ(b.data()[2], 2); | ||
|
||
const std::size_t size3 = 6u; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we move it above?
bitmap b3(buf, expected_block_count * 8); | ||
|
||
b2 = b3; | ||
CHECK_EQ(b2.size() , b3.size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CHECK_EQ(b2.size() , b3.size()); | |
CHECK_EQ(b2.size(), b3.size()); |
auto dynamic_bitset_base<B>::count_non_null() const noexcept -> size_type | ||
{ | ||
// Number of bits set to 1 in i for i from 0 to 255 | ||
static constexpr unsigned char table[] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the comment sufficient?
Converted to draft to avoid accidental merge. This PR will be split into many smaller ones. |
Can this PR be closed now? |
No description provided.