我想加入多个视图,而不使用临时变量(如示例中的
arr_and_zeroes
)。但是,这样做会产生编译错误。#include <vector>
#include <ranges>
#include <type_traits>
int main() {
std::vector<int> arr{2, 3, 7, 5};
auto arr_and_zeroes = {{0}, arr, {0}};
static_assert(std::is_same_v<
decltype(arr_and_zeroes),
std::initializer_list<std::vector<int>>
>);
auto r1 = std::views::join(arr_and_zeroes);
// both of those assignments produce compile-time errors:
//auto r2 = std::views::join({{0}, arr, {0}});
//auto r3 = std::views::join(
// std::initializer_list<std::vector<int>>{{0}, arr, {0}}
//);
}
r2
分配时出现错误消息:
bug2.cpp: In function ‘int main()’:
bug2.cpp:15:29: error: no match for call to ‘(const std::ranges::views::_Join) (<brace-enclosed initializer list>)’
15 | auto r2 = std::views::join({{0}, arr, {0}});
| ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
In file included from bug2.cpp:2:
/usr/include/c++/14.2.1/ranges:3227:9: note: candidate: ‘template<class _Range> requires (viewable_range<_Range>) && (__can_join_view<_Range>) constexpr auto
std::ranges::views::_Join::operator()(_Range&&) const’
3227 | operator() [[nodiscard]] (_Range&& __r) const
| ^~~~~~~~
/usr/include/c++/14.2.1/ranges:3227:9: note: template argument deduction/substitution failed:
bug2.cpp:15:29: note: couldn’t deduce template parameter ‘_Range’
15 | auto r2 = std::views::join({{0}, arr, {0}});
| ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
r3
分配时出现错误消息:
bug2.cpp: In function ‘int main()’:
bug2.cpp:16:29: error: no match for call to ‘(const std::ranges::views::_Join) (std::initializer_list<std::vector<int> >)’
16 | auto r3 = std::views::join(
| ~~~~~~~~~~~~~~~~^
17 | std::initializer_list<std::vector<int>>{{0}, arr, {0}}
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18 | );
| ~
In file included from bug2.cpp:2:
/usr/include/c++/14.2.1/ranges:3227:9: note: candidate: ‘template<class _Range> requires (viewable_range<_Range>) && (__can_join_view<_Range>) constexpr auto std::ranges::views::_Join::operator()(_Range&&) const’
3227 | operator() [[nodiscard]] (_Range&& __r) const
| ^~~~~~~~
/usr/include/c++/14.2.1/ranges:3227:9: note: template argument deduction/substitution failed:
/usr/include/c++/14.2.1/ranges:3227:9: note: constraints not satisfied
In file included from /usr/include/c++/14.2.1/bits/ranges_util.h:34,
from /usr/include/c++/14.2.1/tuple:44,
from /usr/include/c++/14.2.1/bits/uses_allocator_args.h:39,
from /usr/include/c++/14.2.1/bits/memory_resource.h:41,
from /usr/include/c++/14.2.1/vector:87,
from bug2.cpp:1:
bug2.cpp: In substitution of ‘template<class _Range> requires (viewable_range<_Range>) && (__can_join_view<_Range>) constexpr auto std::ranges::views::_Join::operator()(_Range&&) const [with _Range = std::initializer_list<std::vector<int> >]’:
bug2.cpp:16:29: required from here
16 | auto r3 = std::views::join(
| ~~~~~~~~~~~~~~~~^
17 | std::initializer_list<std::vector<int>>{{0}, arr, {0}}
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18 | );
| ~
/usr/include/c++/14.2.1/bits/ranges_base.h:808:13: required for the satisfaction of ‘viewable_range<_Range>’ [with _Range = std::initializer_list<std::vector<int, std::allocator<int> > >]
/usr/include/c++/14.2.1/bits/ranges_base.h:810:11: note: no operand of the disjunction is satisfied
809 | && ((view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>, _Tp>)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
810 | || (!view<remove_cvref_t<_Tp>>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
811 | && (is_lvalue_reference_v<_Tp>
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
812 | || (movable<remove_reference_t<_Tp>>
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
813 | && !__detail::__is_initializer_list<remove_cvref_t<_Tp>>))));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: note: set ‘-fconcepts-diagnostics-depth=’ to at least 2 for more detail
看来 join 必须传递一个
viewable_range
,其概念概述如下:
template< class T >
concept viewable_range =
ranges::range<T> &&
((ranges::view<std::remove_cvref_t<T>> &&
std::constructible_from<std::remove_cvref_t<T>, T>) ||
(!ranges::view<std::remove_cvref_t<T>> &&
(std::is_lvalue_reference_v<T> ||
(std::movable<std::remove_reference_t<T>> && !/*is-initializer-list*/<T>))));
参考最后一行,明确不允许初始化列表,除非
std::remove_cvref_t<T>
是 std::initializer_list
的特化。
您可以查看 cppreference 来查看可行的
viewable_ranges
的示例。
如果您使用的是 C++26,则可以使用
std::ranges::views::concat
代替:
int main() {
using namespace std::views;
std::vector<int> arr{2, 3, 7, 5};
auto cat = concat(single(0), arr, single(0));
}
如果您不使用 C++26,创建临时并使用 join 可能是最简单的解决方案,而无需自己实现 concat。