当我混合使用boost::join
和std::views::transform
输出时(如下所示),我遇到了意外的行为。编译器没有发出任何警告。幸运的是,地址检查器在get2b()
中检测到了无效的内存访问。
get1b()
函数遵循与get2b()
相同的模式,但该代码可以正常工作。考虑到 UB 的可能性,我怎样才能确定构建的范围是合法的?我的偏执心希望将get1b()
写成return std::move(rng) | ...
。
https://www.godbolt.org/z/Y77YW3jYb
#include <array>
#include <ranges>
#include <algorithm>
#include <iostream>
#include <iterator>
#include "boost/range/join.hpp"
#include "boost/range/adaptor/transformed.hpp"
inline auto square = [](int x) { return x*x; };
struct A {
std::array<std::vector<int>, 3> m_data{ std::vector{1, 2}, std::vector{3, 4, 5}, std::vector{6} };
auto join1() const { return m_data | std::views::join; }
auto join2() const { return boost::join(m_data[0], boost::join(m_data[1], m_data[2])); }
auto get1a() const { return join1() | std::views::transform(square); }
auto get1b() const { auto rng = join1(); return rng | std::views::transform(square); }
#if __GNUC__ >= 12
auto get2a() const { return join2() | std::views::transform(square); }
#endif
auto get2b() const { auto rng = join2(); return rng | std::views::transform(square); }
auto get2c() const { auto rng = join2(); return rng | boost::adaptors::transformed(square); }
};
template<std::ranges::range R>
void print(R&& r)
{
std::ranges::copy(r, std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
}
int main()
{
print(A{}.get1a());
print(A{}.get1b());
#if __GNUC__ >= 12
print(A{}.get2a());
#endif
// print(A{}.get2b()); <-- undefined behavior
print(A{}.get2c());
return 0;
}
附注:我这么做的唯一原因是因为我的团队成员受到了Intellisense无法在IDE上正常工作的影响,最终是由https://github.com/llvm/llvm-project/issues/44178引起的。 (叹气)
get2b()
,你需要这样做。 - 康桓瑋get1a()
一样。一个结果是std::ranges::owning_view
,另一个结果是std::ranges::ref_view
。我理解为什么owning_view
正确工作。然而,原始问题仍然存在。 - MarkB