I have the following function:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <ranges>
#include <span>
#include <type_traits>
template <typename T>
concept arithmetic = std::is_arithmetic_v<T>;
template <arithmetic T, std::size_t N>
auto sum(std::span<T, N> const a,
std::span<T, N> const b,
std::span<T, N> const c)
{
std::ranges::transform(a, b, std::begin(c),
[](auto const a, auto const b) { return a + b; });
}
When I try to call it like the following:
std::array<int, 10> a{};
std::array<int, 10> b{};
std::array<int, 10> c{};
// more initialisation for a, b, and c
// ...
sum(a, b, c);
I receive the following template deduction error:
<source>:41:5: error: no matching function for call to 'sum'
sum(a, b, c);
^~~
<source>:15:10: note: candidate template ignored: could not match 'span' against 'array'
auto sum(span_const_of_const<T, N> a,
^
I need to fix the call with explicit constructors to std::span, like so:
sum(std::span(a), std::span(b), std::span(c));
I was under the impression that std::span meant I didn't have to do this. What am I doing wrong here?
Template argument deduction does not consider conversions. If you don't deduce the arguments then you don't have to specify span.
Alternatively, you could deduce the arguments and constrain them to allow construction of a
std::span<arithmetic, N>Godbolt link