我正在阅读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"
分配给iter
,success
会是什么?!?围绕它的另一种方式将违反表达式部分。但是它显然可以编译并运行,所以我必须缺少一些东西
答案 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)
}
在上面的示例中,将a
和b
推导为foo
任务的任何返回类型,而与下面的if
条件无关。