C ++ 17中的初始化程序列表和结构化绑定推论含糊不清 [英] Initializer list and structured bindings deduction ambiguity in C++17
问题描述
我总是避免像下面这样的初始化
const auto&x = a,y = b;const int * const x = ptr_1,* const y = ptr_2;//wot
由于引用限定符和指针限定符不适用于两个初始化.既然这是初学者学习的第一手东西,它的含糊不清让我感到以下内容更加清晰,并且不需要读者多加思考
const auto&x = a;const auto&y = b;
有了C ++ 17和结构化绑定,我很高兴并且看到了很多潜力.C ++ 17宣布C ++ 14和C ++ 11无法修复的内容为非法, auto x {1}
是 int
而不是 std ::initializer_list< int>
.但是,为什么下面的代码不起作用?
const auto&[x,y] {a,b};const auto&[x,y] = {a,b};
后者与自动推论和初始化列表的新规则保持一致,右侧的表达式被视为初始化列表.但是对于以前的编译失败,并显示以下错误
类型为'const auto&'的变量'[a,b]'的初始化程序包含多个表达式
有什么方法可以用结构化绑定语法声明x和y,而不必求助于元组,对等?另外,为什么上面的代码示例中的前者格式错误?该语法有歧义吗?
结构化绑定可以说是解包"的意思.事物.它不是设计为组合常规声明的方法.尽管外观,该 const auto&
不适用于 a
和 b
.
您的特定尝试违反了 [dcl.dcl]/8 :
带有标识符列表的简单声明被称为结构化绑定声明([dcl.struct.bind]).[...]初始化程序的形式应为"
= 赋值表达式
",形式应为"{ assignment-expression }
",或格式为"( assignment-expression
" ),其中 assignment-expression 是数组或非工会类类型.
int a = 1,b = 2;const auto bitand<:x,y:>= std :: tie(a,b);
此结构化绑定声明(非常)大致等于
const auto bitand __e = std :: tie(a,b);//隐藏的变量auto和x = std :: get< 0>(__ e);auto和y = std :: get< 1>(__ e);
(真实的东西使用 tuple_element
,而不是 auto
.)
注意:
-
const自动位和
适用于隐藏变量,并且仅适用于隐藏变量.即使仅编写auto
,x
和y
始终是引用;其引用对象是否为const
取决于初始化程序类型的const
传播属性. - 从prvalue初始化程序实现的临时对象将通过引用绑定来延长其寿命.
- 在此示例中,
x
和y
均为"reference to int"类型;编写x = 1;
是有效的. - 在
decltype
措词中对结构化绑定有特殊处理.
const
实际上并不会影响引用者的常数.OTOH,如果您想对结构化绑定声明不打算使用的内容使用它们,那将是一个很大的惊喜.I had always avoided initializations like the following
const auto& x = a, y = b;
const int* const x = ptr_1, *const y = ptr_2; // wot
For the reason that the reference and pointer qualifiers don't apply to both the initializations. Granted it's one of the first things beginners learn, the ambiguity associated with it makes me feel like the following is clearer and requires less thought on the reader's end
const auto& x = a;
const auto& y = b;
With C++17 and structured bindings I was happy and saw lots of potential. C++17 outlawed what C++14 and C++11 had failed to fix, auto x {1}
is an int
and not std::initializer_list<int>
. But why does the following code not work?
const auto& [x, y] {a, b};
const auto& [x, y] = {a, b};
The latter is in line with the new rules for auto deduction and initializer lists, the expression on the right hand side is treated as an initializer list. But for the former compilation fails with the following error
initializer for variable '[a, b]' with type 'const auto &' contains multiple expressions
Is there any way I can declare both x and y with the structured bindings syntax without having to resort to tuples, pairs and the like? Also why is the former in the code example above ill formed code? Is there an ambiguity in that syntax?
Structured binding is, so to speak, for "unpacking" things. It's not designed to be a way to combine normal declarations. That const auto&
applies to neither a
nor b
, despite the appearance.
Your particular attempt violates [dcl.dcl]/8:
A simple-declaration with an identifier-list is called a structured binding declaration ([dcl.struct.bind]). [...] The initializer shall be of the form "
= assignment-expression
", of the form "{ assignment-expression }
", or of the form "( assignment-expression )
", where the assignment-expression is of array or non-union class type.
int a = 1, b = 2;
const auto bitand <:x, y:> = std::tie(a, b);
This structured binding declaration is (very) roughly equivalent to
const auto bitand __e = std::tie(a, b); // hidden variable
auto and x = std::get<0>(__e);
auto and y = std::get<1>(__e);
(The real thing uses tuple_element
, not auto
.)
Notes:
- The
const auto bitand
applies to the hidden variable and only the hidden variable.x
andy
are always references even if you write justauto
; whether their referent isconst
depends on theconst
propagation properties of the initializer's type. - A temporary materialized from a prvalue initializer will have its lifetime extended by the reference binding.
- In this example, both
x
andy
are of type "reference to int"; it is valid to writex = 1;
. - There's special treatment for structured bindings in the
decltype
wording.
These semantics are unsurprising if we are talking about unpacking a struct, etc., with two "reference to int" members; a const
on such things doesn't actually affect the referent's constness. OTOH, you are in for a bad surprise if you want to use structured binding declarations for something they aren't designed to do.
这篇关于C ++ 17中的初始化程序列表和结构化绑定推论含糊不清的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!