我可以对 boost::adaptors::transformed 的结果使用 boost::copy_range 而不是 std::array 来取回另一个 std::array 吗?
Can I use boost::copy_range on the result of boost::adaptors::transformed over std::array to get back another std::array?
此代码有效并生成正确的输出(23
,因为 2
和 3
是 array_of_vectors
中两个 std::vector<int>
的大小:
#include <array>
#include <boost/range/adaptor/transformed.hpp>
#include <iostream>
#include <vector>
using boost::adaptors::transformed;
constexpr auto get_size = [](auto const& snip){ return snip.size(); };
int main() {
std::array<std::vector<int>,2> array_of_vectors = {
{std::vector<int>{1,1}, std::vector<int>{1,1,1}}
};
auto array_of_sizes = array_of_vectors | transformed(get_size);
for (auto i : array_of_sizes) {
std::cout << i;
}
}
另一方面,如果我尝试通过更改 boost::copy_range
来强制执行 array_of_sizes
确实是 std::array<std::size_t, 2u>
std::array<std::size_t, 2u>
auto array_of_sizes = array_of_vectors | transformed(get_size);
至此
auto array_of_sizes = boost::copy_range<std::array<std::size_t, 2u>>(
array_of_vectors | transformed(get_size)
);
我收到以下错误,
$ g++ -std=c++17 deleteme.cpp && ./a.out
In file included from /usr/include/boost/range/iterator_range.hpp:13,
from /usr/include/boost/range/adaptor/transformed.hpp:16,
from deleteme.cpp:2:
/usr/include/boost/range/iterator_range_core.hpp: In instantiation of ‘SeqT boost::copy_range(const Range&) [with SeqT = std::array<long unsigned int, 2>; Range = boost::range_detail::transformed_range<<lambda(const auto:1&)
2> >]’:
deleteme.cpp:16:114: required from here
/usr/include/boost/range/iterator_range_core.hpp:842:20: error: no matching function for call to ‘std::array<long unsigned int, 2>::array(boost::range_detail::extract_const_iterator<boost::range_detail::transformed_range<<la
y<std::vector<int>, 2> >, true>::type, boost::range_detail::extract_const_iterator<boost::range_detail::transformed_range<<lambda(const auto:1&)>, std::array<std::vector<int>, 2> >, true>::type)’
842 | return SeqT( boost::begin( r ), boost::end( r ) );
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from deleteme.cpp:1:
/usr/include/c++/10.2.0/array:94:12: note: candidate: ‘std::array<long unsigned int, 2>::array()’
94 | struct array
| ^~~~~
/usr/include/c++/10.2.0/array:94:12: note: candidate expects 0 arguments, 2 provided
/usr/include/c++/10.2.0/array:94:12: note: candidate: ‘constexpr std::array<long unsigned int, 2>::array(const std::array<long unsigned int, 2>&)’
/usr/include/c++/10.2.0/array:94:12: note: candidate expects 1 argument, 2 provided
/usr/include/c++/10.2.0/array:94:12: note: candidate: ‘constexpr std::array<long unsigned int, 2>::array(std::array<long unsigned int, 2>&&)’
/usr/include/c++/10.2.0/array:94:12: note: candidate expects 1 argument, 2 provided
另一方面,最令我惊讶的是 (!),如果我强制 array_of_sizes
成为 std::vector<std::size_t>
,例如
auto array_of_sizes = boost::copy_range<std::vector<std::size_t>>( // vector instead of array
array_of_vectors | transformed(get_size)
);
有效!看起来 transformed
将 std::array<T,N>
转换为可转换为 std::vector<T>
的范围,就像它忘记了 std::array
的编译时大小一样。
这是什么 error/behavior 原因?
我只能认为某些东西不起作用是因为 std::array
的编译时已知大小,而不是 std::vector
的 运行 时间大小。可能 transformed
无法处理?或者可能是 copy_range
而不能?
如果你用 -std=c++2a
编译,gcc 10.2 有一个很好的错误信息:
boost_1_74_0/boost/range/iterator_range_core.hpp:842:38: error: array must be initialized with a brace-enclosed initializer
842 | return SeqT( boost::begin( r ), boost::end( r ) );
| ~~~~~~~~~~~~^~~~~
问题是 boost::copy_range
只知道如何构造将迭代器对作为(其中一个)构造函数参数的容器,因此它与实际上没有任何迭代器的 std::array
不兼容构造函数 - 它只能作为(支撑的)元素列表的聚合来构造。
使用 C++20 的 lambda,您可以编写一个替代函数,使用简单的元编程来生成该元素列表:
template<class T, class R>
T copy_range_fixed_size(R const& r) {
return [&r]<std::size_t... I>(std::index_sequence<I...>) {
auto it = boost::begin(r);
return T{(I, *it++)...};
}(std::make_index_sequence<T{}.size()>{});
}
此代码有效并生成正确的输出(23
,因为 2
和 3
是 array_of_vectors
中两个 std::vector<int>
的大小:
#include <array>
#include <boost/range/adaptor/transformed.hpp>
#include <iostream>
#include <vector>
using boost::adaptors::transformed;
constexpr auto get_size = [](auto const& snip){ return snip.size(); };
int main() {
std::array<std::vector<int>,2> array_of_vectors = {
{std::vector<int>{1,1}, std::vector<int>{1,1,1}}
};
auto array_of_sizes = array_of_vectors | transformed(get_size);
for (auto i : array_of_sizes) {
std::cout << i;
}
}
另一方面,如果我尝试通过更改 boost::copy_range
来强制执行 array_of_sizes
确实是 std::array<std::size_t, 2u>
std::array<std::size_t, 2u>
auto array_of_sizes = array_of_vectors | transformed(get_size);
至此
auto array_of_sizes = boost::copy_range<std::array<std::size_t, 2u>>(
array_of_vectors | transformed(get_size)
);
我收到以下错误,
$ g++ -std=c++17 deleteme.cpp && ./a.out
In file included from /usr/include/boost/range/iterator_range.hpp:13,
from /usr/include/boost/range/adaptor/transformed.hpp:16,
from deleteme.cpp:2:
/usr/include/boost/range/iterator_range_core.hpp: In instantiation of ‘SeqT boost::copy_range(const Range&) [with SeqT = std::array<long unsigned int, 2>; Range = boost::range_detail::transformed_range<<lambda(const auto:1&)
2> >]’:
deleteme.cpp:16:114: required from here
/usr/include/boost/range/iterator_range_core.hpp:842:20: error: no matching function for call to ‘std::array<long unsigned int, 2>::array(boost::range_detail::extract_const_iterator<boost::range_detail::transformed_range<<la
y<std::vector<int>, 2> >, true>::type, boost::range_detail::extract_const_iterator<boost::range_detail::transformed_range<<lambda(const auto:1&)>, std::array<std::vector<int>, 2> >, true>::type)’
842 | return SeqT( boost::begin( r ), boost::end( r ) );
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from deleteme.cpp:1:
/usr/include/c++/10.2.0/array:94:12: note: candidate: ‘std::array<long unsigned int, 2>::array()’
94 | struct array
| ^~~~~
/usr/include/c++/10.2.0/array:94:12: note: candidate expects 0 arguments, 2 provided
/usr/include/c++/10.2.0/array:94:12: note: candidate: ‘constexpr std::array<long unsigned int, 2>::array(const std::array<long unsigned int, 2>&)’
/usr/include/c++/10.2.0/array:94:12: note: candidate expects 1 argument, 2 provided
/usr/include/c++/10.2.0/array:94:12: note: candidate: ‘constexpr std::array<long unsigned int, 2>::array(std::array<long unsigned int, 2>&&)’
/usr/include/c++/10.2.0/array:94:12: note: candidate expects 1 argument, 2 provided
另一方面,最令我惊讶的是 (!),如果我强制 array_of_sizes
成为 std::vector<std::size_t>
,例如
auto array_of_sizes = boost::copy_range<std::vector<std::size_t>>( // vector instead of array
array_of_vectors | transformed(get_size)
);
有效!看起来 transformed
将 std::array<T,N>
转换为可转换为 std::vector<T>
的范围,就像它忘记了 std::array
的编译时大小一样。
这是什么 error/behavior 原因?
我只能认为某些东西不起作用是因为 std::array
的编译时已知大小,而不是 std::vector
的 运行 时间大小。可能 transformed
无法处理?或者可能是 copy_range
而不能?
如果你用 -std=c++2a
编译,gcc 10.2 有一个很好的错误信息:
boost_1_74_0/boost/range/iterator_range_core.hpp:842:38: error: array must be initialized with a brace-enclosed initializer
842 | return SeqT( boost::begin( r ), boost::end( r ) );
| ~~~~~~~~~~~~^~~~~
问题是 boost::copy_range
只知道如何构造将迭代器对作为(其中一个)构造函数参数的容器,因此它与实际上没有任何迭代器的 std::array
不兼容构造函数 - 它只能作为(支撑的)元素列表的聚合来构造。
使用 C++20 的 lambda,您可以编写一个替代函数,使用简单的元编程来生成该元素列表:
template<class T, class R>
T copy_range_fixed_size(R const& r) {
return [&r]<std::size_t... I>(std::index_sequence<I...>) {
auto it = boost::begin(r);
return T{(I, *it++)...};
}(std::make_index_sequence<T{}.size()>{});
}