提问人:SRSR333 提问时间:9/13/2023 更新时间:9/13/2023 访问量:70
为什么“std::span”需要在模板化函数中使用显式构造函数?[复制]
Why does `std::span` require an explicit constructor to use in a templated function? [duplicate]
问:
我有以下功能:
#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; });
}
当我尝试像下面这样称呼它时:
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);
我收到以下模板扣分错误:
<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,
^
我需要用显式构造函数修复调用,如下所示:std::span
sum(std::span(a), std::span(b), std::span(c));
我的印象是,这意味着我不必这样做。我在这里做错了什么?std::span
答:
2赞
Caleth
9/13/2023
#1
模板参数推导不考虑转换。如果不推导出参数,则不必指定 span。
sum<int, 10>(a, b, c);
或者,您可以推导出参数并约束它们以允许构造std::span<arithmetic, N>
template <typename T>
concept arithmetic_span_like = std::ranges::range<T>
&& arithmetic<std::ranges::range_value_t<T>>
&& std::constructible_from<std::span<std::ranges::range_value_t<T>>, T>;
template <typename A, typename B>
concept same_size = arithmetic_span_like<A>
&& arithmetic_span_like<B>
&& requires(A a, B b)
{
std::ranges::size(a) == std::ranges::size(b);
};
template <arithmetic_span_like A, arithmetic_span_like B, arithmetic_span_like C>
requires same_size<A, B> && same_size<A, C>
auto sum(A&& a, B&& b, C&& c)
{
std::ranges::transform(a, b, std::begin(c), std::plus{});
}
评论
array
即使可转换为。span
T &&
span<int>
顺便说一句,这将是 2 个有效匹配;-)span<int, 10>
requires N != std::dynamic_extent
sum