c++initializationc++20stdarraystd-span

Can't construct std::span<int> from temporary std::array<int>


I have the following code, which I expected to work, but it doesn't:

#include <array>
#include <span>

void foo(std::span<int>);

int main() {
    foo(std::array<int, 3>{});
}

clang fails to compile this:

<source>:7:5: error: no matching function for call to 'foo'
    7 |     foo(std::array<int, 3>{});
      |     ^~~
<source>:4:6: note: candidate function not viable: no known conversion from 'std::array<int, 3>' to 'std::span<int>' for 1st argument
    4 | void foo(std::span<int>);
      |      ^   ~~~~~~~~~~~~~~

I expected this to call the constructor:

template< class U, std::size_t N >
constexpr span( const std::array<U, N>& arr ) noexcept; // (6)

4-6) Constructs a span that is a view over the array arr; the resulting span has size() == N and data() == std::data(arr).

These overloads participate in overload resolution only if extent == std::dynamic_extent || N == extent is true and the conversion from std::remove_pointer_t<decltype(data(arr))> to element_type is at most a qualification conversion.

See std::span::span on cppreference

Why are the constraints of this constructor not satisfied?

I don't see any reason why I wouldn't be able to call this constructor.


Solution

  • Qualification conversions can only make something more const qualified.

    decltype(data(arr)) is const int* for const std::array<int, 3>&. const int can not be converted to int via a qualification conversion.

    std::span<const int>(std::array<int, 3>{}) does work however (const int -> const int).