glades
glades

Reputation: 4848

std::span of a vector<bool> doesn't compile

Let's preface it by stating once again that std::vector<bool> was a mistake.
But now it finally bit me. This doesn't compile:

LiveDemo

#include <iostream>
#include <span>
#include <vector>
#include <cstdint>

int main()
{
    std::vector<uint8_t> intvec = { 1, 2, 3, 4 };
    auto vec_int_view = std::span(intvec);

      // This will not compile:
//    std::vector<bool> boolvec = { true, false, true, true };
//    auto vec_bool_view = std::span(boolvec);
}

Errors:

<source>: In function 'int main()':
<source>:13:43: error: class template argument deduction failed:
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
<source>:13:43: error: no matching function for call to 'span(std::vector<bool>&)'
In file included from <source>:2:
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:233:9: note: candidate: 'template<class _Type, long unsigned int _Extent, class _OType, long unsigned int _OExtent>  requires (_Extent == std::dynamic_extent || _OExtent == std::dynamic_extent || _Extent == _OExtent) && (std::__is_array_convertible<_Type, _OType>::value) span(const std::span<_OType, _OExtent>&)-> std::span<_Type, _Extent>'
  233 |         span(const span<_OType, _OExtent>& __s) noexcept
      |         ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:233:9: note:   template argument deduction/substitution failed:
<source>:13:43: note:   'std::vector<bool>' is not derived from 'const std::span<_OType, _OExtent>'
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:225:7: note: candidate: 'template<class _Type, long unsigned int _Extent> span(const std::span<_Tp, _Num>&)-> std::span<_Type, _Extent>'
  225 |       span(const span&) noexcept = default;
      |       ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:225:7: note:   template argument deduction/substitution failed:
<source>:13:43: note:   'std::vector<bool>' is not derived from 'const std::span<_Tp, _Num>'
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:213:9: note: candidate: 'template<class _Type, long unsigned int _Extent, class _Range>  requires !(__is_span<typename std::remove_cvref<_I2>::type>) && !(__is_std_array<typename std::remove_cvref<_I2>::type>) && !(is_array_v<typename std::remove_cvref<_I2>::type>) && (contiguous_range<_Range>) && (sized_range<_Range>) && ((borrowed_range<_Range>) || (is_const_v<_Type>)) && (std::__is_compatible_ref<decltype(*(declval<decltype(std::ranges::__access::__begin((declval<_Range&>)()))&>)())>::value) span(_Range&&)-> std::span<_Type, _Extent>'
  213 |         span(_Range&& __range)
      |         ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:213:9: note:   template argument deduction/substitution failed:
<source>:13:43: note:   couldn't deduce template parameter '_Type'
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:201:9: note: candidate: 'template<class _Type, long unsigned int _Extent, class _Tp, long unsigned int _ArrayExtent>  requires  std::span<_Tp, _Num>::__is_compatible_array::value span(const std::array<_Tp, _ArrayExtent>&)-> std::span<_Type, _Extent>'
  201 |         span(const array<_Tp, _ArrayExtent>& __arr) noexcept
      |         ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:201:9: note:   template argument deduction/substitution failed:
<source>:13:43: note:   'std::vector<bool>' is not derived from 'const std::array<_Tp, _ArrayExtent>'
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:194:9: note: candidate: 'template<class _Type, long unsigned int _Extent, class _Tp, long unsigned int _ArrayExtent>  requires  std::span<_Tp, _Num>::__is_compatible_array::value span(std::array<_Tp, _ArrayExtent>&)-> std::span<_Type, _Extent>'
  194 |         span(array<_Tp, _ArrayExtent>& __arr) noexcept
      |         ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:194:9: note:   template argument deduction/substitution failed:
<source>:13:43: note:   'std::vector<bool>' is not derived from 'std::array<_Tp, _ArrayExtent>'
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:187:9: note: candidate: 'template<class _Type, long unsigned int _Extent, long unsigned int _ArrayExtent>  requires  _Extent == std::dynamic_extent || _ArrayExtent == _Extent span(std::type_identity_t<_Type> (&)[_ArrayExtent])-> std::span<_Type, _Extent>'
  187 |         span(type_identity_t<element_type> (&__arr)[_ArrayExtent]) noexcept
      |         ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:187:9: note:   template argument deduction/substitution failed:
<source>:13:43: note:   mismatched types 'std::type_identity_t<_Type> [_ArrayExtent]' and 'std::vector<bool>'
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:172:9: note: candidate: 'template<class _Type, long unsigned int _Extent, class _It, class _End>  requires (contiguous_iterator<_It>) && (sized_sentinel_for<_End, _It>) && ((std::__is_compatible_ref<decltype(*(declval<_I2&>)())>::value) && !(is_convertible_v<_End, long unsigned int>)) span(_It, _End)-> std::span<_Type, _Extent>'
  172 |         span(_It __first, _End __last)
      |         ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:172:9: note:   candidate expects 2 arguments, 1 provided
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:157:9: note: candidate: 'template<class _Type, long unsigned int _Extent, class _It>  requires (contiguous_iterator<_It>) && (std::__is_compatible_ref<decltype(*(declval<_I2&>)())>::value) span(_It, std::size_t)-> std::span<_Type, _Extent>'
  157 |         span(_It __first, size_type __count)
      |         ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:157:9: note:   candidate expects 2 arguments, 1 provided
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:149:7: note: candidate: 'template<class _Type, long unsigned int _Extent> span()-> std::span<_Type, _Extent> requires  _Extent == std::dynamic_extent || _Extent == 0'
  149 |       span() noexcept
      |       ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:149:7: note:   candidate expects 0 arguments, 1 provided
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:54:11: note: candidate: 'template<class _Type, long unsigned int _Extent> span(std::span<_Type, _Extent>)-> std::span<_Type, _Extent>'
   54 |     class span;
      |           ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:54:11: note:   template argument deduction/substitution failed:
<source>:13:43: note:   'std::vector<bool>' is not derived from 'std::span<_Type, _Extent>'
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:466:5: note: candidate: 'template<class _Range>  requires  contiguous_range<_Range> std::span(_Range&&)-> span<typename remove_reference<ranges::range_reference_t<_Range&> >::type>'
  466 |     span(_Range &&)
      |     ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:466:5: note:   template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:466:5: note: constraints not satisfied
In file included from /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/compare:40,
                 from /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/char_traits.h:56,
                 from /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/ios:42,
                 from /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/ostream:40,
                 from /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/iostream:41,
                 from <source>:1:
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/concepts: In substitution of 'template<class _Range>  requires  contiguous_range<_Range> std::span(_Range&&)-> span<typename remove_reference<ranges::range_reference_t<_Range&> >::type> [with _Range = std::vector<bool>&]':
<source>:13:43:   required from here
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/concepts:74:13:   required for the satisfaction of 'derived_from<typename std::__detail::__iter_concept_impl<_Iter>::type, std::contiguous_iterator_tag>' [with _Iter = std::_Bit_iterator]
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/iterator_concepts.h:697:13:   required for the satisfaction of 'contiguous_iterator<decltype (std::ranges::__access::__begin(declval<_Container&>()))>' [with _Tp = std::vector<bool, std::allocator<bool> >&]
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/ranges_base.h:607:13:   required for the satisfaction of 'contiguous_range<_Range>' [with _Range = std::vector<bool, std::allocator<bool> >&]
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/concepts:74:28: note:   'std::contiguous_iterator_tag' is not a base of 'std::random_access_iterator_tag'
   74 |     concept derived_from = __is_base_of(_Base, _Derived)
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:462:5: note: candidate: 'template<class _Iter, class _End>  requires  contiguous_iterator<_Iter> std::span(_Iter, _End)-> span<typename remove_reference<iter_reference_t<_Tp> >::type>'
  462 |     span(_Iter, _End)
      |     ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:462:5: note:   candidate expects 2 arguments, 1 provided
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:458:5: note: candidate: 'template<class _Type, long unsigned int _ArrayExtent> std::span(const array<_Tp, _Nm>&)-> span<const _Type, _ArrayExtent>'
  458 |     span(const array<_Type, _ArrayExtent>&)
      |     ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:458:5: note:   template argument deduction/substitution failed:
<source>:13:43: note:   'std::vector<bool>' is not derived from 'const std::array<_Tp, _Nm>'
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:455:5: note: candidate: 'template<class _Type, long unsigned int _ArrayExtent> std::span(array<_Tp, _Nm>&)-> span<_Tp, _Num>'
  455 |     span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>;
      |     ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:455:5: note:   template argument deduction/substitution failed:
<source>:13:43: note:   'std::vector<bool>' is not derived from 'std::array<_Tp, _Nm>'
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:452:5: note: candidate: 'template<class _Type, long unsigned int _ArrayExtent> std::span(_Type (&)[_ArrayExtent])-> span<_Tp, _Num>'
  452 |     span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>;
      |     ^~~~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/span:452:5: note:   template argument deduction/substitution failed:
<source>:13:43: note:   mismatched types '_Type [_ArrayExtent]' and 'std::vector<bool>'
   13 |     auto vec_bool_view = std::span(boolvec);
      |                                           ^

What are my options here? Just use std::vector<uint8_t>?
I almost thought I could finally make use of this vector optimisation.. :/

Upvotes: 2

Views: 189

Answers (1)

wohlstad
wohlstad

Reputation: 29009

std::span:

describes an object that can refer to a contiguous sequence of objects with the first element of the sequence at position zero.

This means std::span<T> can refer to a contigous sequences of Ts.
However std::vector<bool>:

Does not necessarily store its elements as a contiguous array.

So the two do not match.
Morover - std::vector<bool> is not a proper std container at all, since it does not guarantee all the Container requirements.

If it's important for you to use a span into the sequence, I would go with std::vector<uint8_t>.

If it's not a must, and you want to keep memory footprint compact, you can have a look at std::bitset.

In any case I would not use std::vector<bool> if I have a choice.
See more about it here: Is the use of std::vector<bool> objects in C++ acceptable, or should I use an alternative?.

Upvotes: 5

Related Questions