Closed Babalion closed 3 years ago
This is expected behavior, due to std::vector<bool>
being a special case.
std::vector<bool>
does not necessarily store its entries as an array of bool
, so you can't just use the default mdspan
accessor.std::vector<bool>
even have a .data()
method. Regarding (1), it should be possible to write a custom accessor for mdspan
that would view an existing std::vector<bool>
's elements. You can't use the default mdspan
accessor, because it would incorrectly assume that you have a contiguous array of bool
. That's not how std::vector<bool>
works. It's more like a bitset, that has the freedom to store each Boolean value in a bit. The type that nonconst operator[]
returns isn't bool&
, it's a special "proxy reference" type (since C++ doesn't have the idea of a "reference to a bit in a word").
@crtrott check this out
template<class T>
requires(std::is_same_v<T, bool> || std::is_same_v<T, const bool>)
class VectorBoolAccessor {
static constexpr bool is_const = std::is_same_v<T, const bool>;
public:
using element_type = T;
using reference = std::conditional_t<is_const,
std::vector<bool>::const_reference,
std::vector<bool>::reference>;
struct pointer {
using raw_pointer = std::conditional_t<is_const, const std::vector<bool>*, std::vector<bool>*>;
raw_pointer ptr{};
std::size_t offset = 0;
pointer() = default;
pointer(raw_pointer thePtr, std::size_t theOffset = 0) : ptr(thePtr), offset(theOffset) {}
};
using offset_policy = VectorBoolAccessor<T>;
VectorBoolAccessor() = default;
template<class U>
requires(std::is_same_v<T, U> || is_const)
VectorBoolAccessor(const VectorBoolAccessor<U>&) {}
reference access(pointer p, std::size_t i) const {
return (*(p.ptr))[p.offset + i];
}
offset_policy::pointer offset(pointer p, std::size_t i) const {
return {p.ptr, p.offset + i};
}
};
Accessors are awesome aren't they :-)
Consider the following code-snippet:
Obviously I'm trying to create a mdspan of a
std::vector<bool>
, but the following error occurs with CLang 12.0.1: