使用结构化绑定标记为const的变量不是const [英] Variables marked as const using structured bindings are not const
问题描述
我一直在编写一组类,以实现简单的类似于python的 zip
函数。以下代码段(几乎)按预期工作。但是,两个变量 a
和 b
不是 const
I have been writing a set of classes to allow for a simple python-like zip
-function. The following snippet works (almost) just as expected. However, the two variables a
and b
are not const
.
std::vector<double> v1{0.0, 1.1, 2.2, 3.3};
std::vector<int> v2{0, 1, 2};
for (auto const& [a, b] : zip(v1, v2))
{
std::cout << a << '\t' << b << std::endl;
a = 3; // I expected this to give a compiler error, but it does not
std::cout << a << '\t' << b << std::endl;
}
我一直在使用gcc 7.3.0。
这是MCVE:
I have been using gcc 7.3.0. Here is the MCVE:
#include <iostream>
#include <tuple>
#include <vector>
template <class ... Ts>
class zip_iterator
{
using value_iterator_type = std::tuple<decltype( std::begin(std::declval<Ts>()))...>;
using value_type = std::tuple<decltype(*std::begin(std::declval<Ts>()))...>;
using Indices = std::make_index_sequence<sizeof...(Ts)>;
value_iterator_type i;
template <std::size_t ... I>
value_type dereference(std::index_sequence<I...>)
{
return value_type{*std::get<I>(i) ...};
}
public:
zip_iterator(value_iterator_type it) : i(it) {}
value_type operator*()
{
return dereference(Indices{});
}
};
template <class ... Ts>
class zipper
{
using Indices = std::make_index_sequence<sizeof...(Ts)>;
std::tuple<Ts& ...> values;
template <std::size_t ... I>
zip_iterator<Ts& ...> beginner(std::index_sequence<I...>)
{
return std::make_tuple(std::begin(std::get<I>(values)) ...);
}
public:
zipper(Ts& ... args) : values{args...} {}
zip_iterator<Ts& ...> begin()
{
return beginner(Indices{});
}
};
template <class ... Ts>
zipper<Ts& ...> zip(Ts& ... args)
{
return {args...};
}
int main()
{
std::vector<double> v{1};
auto const& [a] = *zip(v).begin();
std::cout << a << std::endl;
a = 2; // I expected this to give a compiler error, but it does not
std::cout << a << std::endl;
}
推荐答案
您有一个引用,这意味着引用本身将是 const
限定的(格式不正确,但在这种情况下忽略),而不是它引用的值。
You have a tuple of a reference, which means that the reference itself will be const
qualified (which is ill-formed but in this context ignored), not the value referenced by it.
int a = 7;
std::tuple<int&> tuple = a;
const auto&[aa] = tuple;
aa = 9; // ok
如果您看 std :: get
已定义,您将看到它为结构化结构返回 const std :: tuple_element< 0,std :: tuple< int&>&
绑定以上。由于第一个元组元素是引用,因此 const&
不起作用,因此可以修改返回值。
If you look how std::get
is defined, you'll see that it returns const std::tuple_element<0, std::tuple<int&>>&
for the structured binding above. As the first tuple element is a reference, the const&
has no effect, and thus you can modify the return value.
真的,如果您有一个类指针/引用成员可以在 const
限定成员函数(即指向/引用的值)中进行修改,那也是一样。
Really, it's same thing if you have a class pointer/reference member that you can modify in a const
qualified member function (the value pointed/referenced that is).
这篇关于使用结构化绑定标记为const的变量不是const的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!