结构绑定声明示例中的if-with-initializer不良吗?

时间:2018-12-14 21:46:59

标签: c++ c++17

我正在阅读Structured binding declaration on cppreference.com

我以为我很好地理解了这些示例,直到我到达底部的最后一个示例为止。

#include <set>
#include <string>
#include <iomanip>
#include <iostream>

int main() {
    std::set<std::string> myset;

    if (auto [iter, success] = myset.insert("Hello"); success) 
        std::cout << "insert is successful. The value is " << 
        std::quoted(*iter) << '\n';
    else
        std::cout << "The value " << std::quoted(*iter) << " already 
        exists in the set\n";
}

乍一看它看起来还不错,但是我看的越多,对if子句的理解就越少。

顶部是列出的可能形式:

  

attr(可选)cv-auto ref-operator(可选)[标识符列表] = expression; (1)

     

attr(可选)cv-auto ref-operator(可选)[标识符列表] {表达式}; (2)

     

attr(可选)cv-auto ref-operator(可选)[标识符列表](表达式); (3)

在我看来,这似乎是推论类型(1)。但这对我来说是没有道理的

  

expression-在顶级(语法上,赋值表达式)不具有逗号运算符,并且具有数组或非联合类类型的表达式。如果expression引用了标识符列表中的任何名称,则声明格式错误。

表示如果表达式在标识符列表中,则声明格式不正确。因此,在我看来,成功不是表达的一部分。如果是这种情况,那么

auto [iter, success] = myset.insert("Hello");

仅将插入的"Hello"分配给itersuccess会是什么?!?围绕它的另一种方式将违反表达式部分。但是它显然可以编译并运行,所以我必须缺少一些东西

2 个答案:

答案 0 :(得分:5)

  

表示如果表达式位于标识符列表中,则声明格式不正确

没有那么说。它表示,如果 expression 使用 identifier-list 中的任何名称,则格式错误。 myset.insert("Hello")不会这样做,所以没关系。

std::set::insert返回一个std::pair<std::set::iterator, bool>,其中std::set::iterator标记元素位置,而bool指示是否插入了元素。因此,auto [iter, success] = myset.insert("Hello")捕获了该对,并将iter设置为std::set::iterator,并将success设置为bool

答案 1 :(得分:1)

我觉得您对结构化绑定和初始化方法感到困惑,但查看它的简单方法是分解它们。

if (auto [a, b] = foo(); b)

由两部分组成=第一个是初始化程序(auto [a, b] = foo()),第二个(b)是条件。它完全等于

{
auto [a, b] = foo(); 
if (b)
}

在上面的示例中,将ab推导为foo任务的任何返回类型,而与下面的if条件无关。