C ++ 17中的初始化程序列表和结构化绑定推论含糊不清 [英] Initializer list and structured bindings deduction ambiguity in C++17

查看:73
本文介绍了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 措词中对结构化绑定有特殊处理.
如果我们正在谈论用两个"int引用"来解压缩一个结构等,这些语义就不足为奇了.成员;在这种情况下的 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 and y are always references even if you write just auto; whether their referent is const depends on the const 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 and y are of type "reference to int"; it is valid to write x = 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆