c++ - 为什么结构化绑定(bind)依赖于 tuple_element?

标签 c++ c++17 structured-bindings

most recent draft结构化绑定(bind)提案(C++17 特性所基于)需要 std::tuple_size、成员 getstd::getstd::tuple_elementPrevious drafts只需要 std::tuple_size 和成员 getstd::get。据我所知,没有关于添加这个的讨论,它只是出现在最终草案中。考虑到我相信它通常可以实现为

,是否有令人信服的理由需要 tuple_element 特化
template<std::size_t index, typename T>
struct tuple_element {
    using type = decltype(std::get<index>(std::declval<T>()));
};

有人知道为什么要添加这个要求吗?

最佳答案

考虑案例:

std::tuple<int, int&>& foo();
auto& [x, y] = foo();

什么是decltype(x)什么是decltype(y) ?语言功能的目标是 x只是 foo().__0 的另一个名称和 y成为 foo().__1 的另一个名称,这意味着它们应该是 intint& , 分别。正如今天所指定的,这将解压缩为:

auto& __e = foo();
std::tuple_element_t<0, decltype(__e)>& x = std::get<0>(__e);
std::tuple_element_t<1, decltype(__e)>& y = std::get<1>(__e);

规则的作用是decltype(x)x 的类型,所以int .和decltype(y)y 的类型,所以int& .

如果我们避开 tuple_element ,通过执行以下操作:

auto&& x = std::get<0>(__e);
auto&& y = std::get<1>(__e);

然后我们无法区分 xy , 因为没有办法区分 std::get<0>(__e)std::get<1>(__e)做:都回馈int& .

这也是增加上述case和普通struct case一致性的方法:

struct C {
    int i;
    int& r;
};
C& bar();
auto& [a, b] = bar();

出于结构化绑定(bind)的目的,我们希望 ab此处的行为方式与 x 相同和 y那里。和ab这里没有引入变量,它们只是 __e.i 的不同名称和 __e.r .


在非引用情况下,有一个不同的场景我们无法区分:

std::tuple<int, int&&> foo();
auto [x, y] = foo();

这里,我们目前通过以下方式解包:

auto __e = foo();
std::tuple_element_t<0, decltype(e)>& x = std::get<0>(std::move(__e));
std::tuple_element_t<1, decltype(e)>& y = std::get<1>(std::move(__e));

两者std::get调用返回 int&& ,因此您无法使用 auto&& 区分它们...但是 tuple_element_t 的结果不同 - intint&& , 分别。这种差异也可以在普通的 struct 案例中看到。


请注意,由于 CWG 2313 ,实际上解包发生在一个唯一命名的变量引用中,绑定(bind)中指定的标识符只是引用这些对象。

关于c++ - 为什么结构化绑定(bind)依赖于 tuple_element?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50064922/

相关文章:

c++ - 返回其参数或检查 nullptr 的函数

c++ - 无法使用 Boost.Bimap 解决 g++ 7.1 结构化绑定(bind)错误

c++ - 结构化绑定(bind)的函数声明

c++ - 地下结构化绑定(bind)实现和 std::tuple

c++ - 异常时解锁互斥量

c++ - 确定 OpenCV 中矩阵的类型

c++ - 带有方法参数的元编程

c++ - C++线程连接会立即返回吗?

c++ - 为什么 <cstring> 中的所有函数都不能有 constexpr?

c++ - 嵌套模板类型的用户定义推导指南