初始化列表和结构化绑定扣歧义C++ 17

问题描述:

我一直回避初始化像下面初始化列表和结构化绑定扣歧义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}; 

后者符合自动扣除和初始化列表的新规则,右侧的表达式被视为初始化列表。但对于前者编译失败,出现以下错误

initializer for variable '[a, b]' with type 'const auto &' contains multiple expressions 

有没有什么办法可以不必诉诸元组,对等的声明x和y与结构化绑定语法?另外为什么上面的代码示例中的前者不适合形成代码?该语法中是否存在歧义?

这种语法只是不支持。您只能解开这对于其std::get已被重载总类和对象:https://skebanga.github.io/structured-bindings/

不幸的是,你不能真正利用酷扣除引导,因为你要a,而不是元组成员的引用。因此你必须写出模板参数列表。

#include <tuple> 

int main() 
{ 
    int a = 1; 
    int b = 2; 
    const auto& [x, y] = std::tuple<int&,int&>{a, b}; 
} 

您也可以不像我一样愚蠢,并正确地阅读文档。

#include <tuple> 

int main() 
{ 
    int a = 1; 
    int b = 2; 
    const auto& [x, y] = std::forward_as_tuple(a, b); 
} 

const auto& [x, y] = std::tie(a, b);也适用。

+1

'const auto&'是可怕的误导。尝试写'x = 1;'。 –

+1

@ T.C。有趣。任何想法为什么'const'在这里被忽略? –

+0

@HenriMenke它的,因为如果你制作一个'std :: tuple ',然后调用'std :: get ',那么'const'不会传播到指向引用的值。当应用于不传播到实际值的指针而是仅传递给指针本身时,它与'const'的问题相同。 – Curious

结构化绑定可以说是“拆包”的东西。它不是为了结合正常的声明而设计的。尽管有外观,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); // hidden variable 
auto and x = std::get<0>(__e); 
auto and y = std::get<1>(__e); 

(真实的东西,使用tuple_element,不auto

注:

  • const auto bitand适用于隐藏变量只有隐藏变量。即使您只写autoxy也始终是引用;是否他们的参考对象是const取决于const传播属性的初始值设定项的类型。
  • 从prvalue初始值设定项临时实现的临时实现将通过参考绑定延长其生命周期。
  • 在这个例子中,xy的类型都是“reference to int”类型;编写x = 1;是有效的。
  • decltype措辞中的结构化绑定有特殊处理。

这些语义并不让人吃惊,如果我们正在讨论用两个“引用int”成员来解压结构等等,一个const这样的东西实际上并不影响指示对象的常量。 OTOH,如果你想将结构化的绑定声明用于他们不打算做的事情,那么你会遇到一个不好的惊喜。

+0

为什么'x'和'y'的类型是'int&'而不是'const int&'? '__e'的类型是'const std :: tuple &',所以调用'std :: get '应该返回一个const引用类型? – Curious

+0

https://wandbox.org/permlink/nK20Qb2omXRRWe9t – Curious

+0

根据你的例子'x'和'y'将始终是引用类型,但在这个例子中,它们不是https://wandbox.org/permlink/Dligcds69j04EwY0 – Curious