来自 std::tuple 的引用绑定类型
Type of reference binding from std::tuple
这里a
的类型是什么?
#include <iostream>
#include <tuple>
using namespace std;
int main()
{
float x{};
std::tuple<int> tpl( x );
auto& [ a ] = tpl;
static_assert( std::is_same_v< decltype( a ), int> );
//static_assert( std::is_same_v< decltype( a ), int&> );
}
根据标准 11.5/3:
[...] Given the type Ti designated by std::tuple_element<i, E>::type
,
variables are introduced with unique names ri of type “reference to
Ti” initialized with the initializer (11.6.3), where the reference is
an lvalue reference if the initializer is an lvalue and an rvalue
reference otherwise. Each vi is the name of an lvalue of type Ti that
refers to the object bound to ri; the referenced type is Ti.
这里,i
是第一个元素 (int) 的 0,E
是 std::tuple<int>
,所以 Ti
的类型是 std::tuple_element<0, std::tuple<int>>::type
,即 int
。此外 ri
(在我们的例子中是 a
)具有类型 "reference to Ti",即左值引用 int&
,而不仅仅是 int
。
那句话有什么问题,为什么编译器 clang 和 gcc 都推导出 int
类型?
备注
the referenced type is Ti.
对于结构化绑定,decltype
生成引用类型 ([dcl.type.decltype]):
if e
is an unparenthesized id-expression naming a structured binding, decltype(e)
is the referenced type as given in the specification of the structured binding declaration;
变量r<sub>0</sub>
的类型确实是int&
。但是 v<sub>0</sub>
,这里叫做 a
,是不同的东西,结构化绑定的名字,从技术上讲不是变量完全不同,只是一种不同的名称。
所以我们需要看decltype
的描述,在[dcl.type.decltype]:
For an expression e
, the type denoted by decltype(e)
is defined as follows:
- if
e
is an unparenthesized id-expression naming a structured binding, decltype(e)
is the referenced type as given in the specification of the structured binding declaration;
所以这里的“引用类型”就是 int
.
当然,decltype((a))
是我们预期的 int&
。没有双括号的名称上的 decltype
用于找出名称是如何“声明”的,而不是名称的行为方式,因此 decltype(a)
“应该”是一回事并不明显,因为a
没有正常的声明。虽然给定 std::tuple<int, int&> t{0, n}; auto& [a, b] = t;
可能有点用处,但我们有 decltype(a)
是 int
但 decltype(b)
是 int&
.
这里a
的类型是什么?
#include <iostream>
#include <tuple>
using namespace std;
int main()
{
float x{};
std::tuple<int> tpl( x );
auto& [ a ] = tpl;
static_assert( std::is_same_v< decltype( a ), int> );
//static_assert( std::is_same_v< decltype( a ), int&> );
}
根据标准 11.5/3:
[...] Given the type Ti designated by
std::tuple_element<i, E>::type
, variables are introduced with unique names ri of type “reference to Ti” initialized with the initializer (11.6.3), where the reference is an lvalue reference if the initializer is an lvalue and an rvalue reference otherwise. Each vi is the name of an lvalue of type Ti that refers to the object bound to ri; the referenced type is Ti.
这里,i
是第一个元素 (int) 的 0,E
是 std::tuple<int>
,所以 Ti
的类型是 std::tuple_element<0, std::tuple<int>>::type
,即 int
。此外 ri
(在我们的例子中是 a
)具有类型 "reference to Ti",即左值引用 int&
,而不仅仅是 int
。
那句话有什么问题,为什么编译器 clang 和 gcc 都推导出 int
类型?
备注
the referenced type is Ti.
对于结构化绑定,decltype
生成引用类型 ([dcl.type.decltype]):
if
e
is an unparenthesized id-expression naming a structured binding,decltype(e)
is the referenced type as given in the specification of the structured binding declaration;
变量r<sub>0</sub>
的类型确实是int&
。但是 v<sub>0</sub>
,这里叫做 a
,是不同的东西,结构化绑定的名字,从技术上讲不是变量完全不同,只是一种不同的名称。
所以我们需要看decltype
的描述,在[dcl.type.decltype]:
For an expression
e
, the type denoted bydecltype(e)
is defined as follows:
- if
e
is an unparenthesized id-expression naming a structured binding,decltype(e)
is the referenced type as given in the specification of the structured binding declaration;
所以这里的“引用类型”就是 int
.
当然,decltype((a))
是我们预期的 int&
。没有双括号的名称上的 decltype
用于找出名称是如何“声明”的,而不是名称的行为方式,因此 decltype(a)
“应该”是一回事并不明显,因为a
没有正常的声明。虽然给定 std::tuple<int, int&> t{0, n}; auto& [a, b] = t;
可能有点用处,但我们有 decltype(a)
是 int
但 decltype(b)
是 int&
.