Mat*_*ing 3 c++ tuples auto c++17 structured-bindings
我希望能够使用 C++ 范围通过压缩容器而不是显式索引它们来帮助简化代码逻辑。我可以让它与详细的 lambda 参数一起使用,但我宁愿尝试使用 more 使其更简单/可概括auto。
const int n = ...;
std::vector<float> a(n), b(n), c(n);
...initialize a and b...
// This works
ranges::for_each(
ranges::views::zip(a, b, c),
[](const std::tuple<float&, float&, float&>& v)
{
const auto& [a, b, c] = v;
c = a + b;
std::cout << typeid(v).name(); // NSt3__15tupleIJRfS1_S1_EEE
}
);
// This fails
ranges::for_each(
ranges::views::zip(a, b, c),
[](const auto& v)
{
const auto& [a, b, c] = v;
// c = a + b;
std::cout << typeid(v).name(); // N6ranges12common_tupleIJRfS1_S1_EEE
}
);
Run Code Online (Sandbox Code Playgroud)
Ranges -v3文档说明如下:
views::zip给定N 个范围,返回一个新范围,其中第 M 个
make_tuple元素是调用所有N个范围的第 M 个元素的结果。
这让我认为我应该能够将 the 转换ranges::common_tuple为 a std::tuple,我查看了公共成员并发现:
std::tuple< Ts... > const & base() const noexcept
Run Code Online (Sandbox Code Playgroud)
然而这也不能编译:
const auto& [a, b, c] = v.base();
// error: no member named 'base' in 'std::__1::tuple<float, float, float>'
Run Code Online (Sandbox Code Playgroud)
但当我打印它时,typeid(v)它不是std::tuple;这是ranges::common_tuple。我在这里尝试使用auto类型推导可以实现什么吗?(clang 编译器,如果这很重要的话)
const简短的答案是:如果您实际上不需要,请不要使用const。你想修改一些东西,为什么const?这工作正常:
ranges::for_each(
ranges::views::zip(a, b, c),
[](auto&& v)
{
auto&& [a, b, c] = v;
c = a + b;
}
);
Run Code Online (Sandbox Code Playgroud)
与较短的一样:
for (auto&& [a, b, c] : ranges::views::zip(a, b, c)) {
c = a + b;
}
Run Code Online (Sandbox Code Playgroud)
你所遇到的问题的原因很微妙。基本上,ranges::for_each受 约束indirectly_unary_invocable,这需要以下所有条件:
invocable<F &, iter_value_t<I> &> &&
invocable<F &, iter_reference_t<I>> &&
invocable<F &, iter_common_reference_t<I>> &&
Run Code Online (Sandbox Code Playgroud)
因此,您的 lambda 会使用所有这三种类型进行实例化。其中一种类型 ( iter_value_t<I>&) 是tuple<float, float, float>&。因此,当您使用 进行结构化绑定时const auto&,每个绑定的类型都是const float。这就是为什么它不可分配的原因 - 但这仅适用于特定的实例化(无论如何都不是在运行时调用的实例化)。
| 归档时间: |
|
| 查看次数: |
944 次 |
| 最近记录: |