Reputation: 848
I was reading through the Structured binding declaration on cppreference.com
I thought I was doing well understanding the examples until I reached the last example at the bottom.
#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";
}
At first glance it looked all right, but the more I looked at it the less I understood the if clause.
At the top are the possible forms listed as:
attr(optional) cv-auto ref-operator(optional) [ identifier-list ] = expression ; (1)
attr(optional) cv-auto ref-operator(optional) [ identifier-list ] { expression } ; (2)
attr(optional) cv-auto ref-operator(optional) [ identifier-list ] ( expression ) ; (3)
To me it looks like to be of deduction type (1). But it kind of makes no sense to me cause of
expression - an expression that does not have the comma operator at the top level (grammatically, an assignment-expression), and has either array or non-union class type. If expression refers to any of the names from identifier-list, the declaration is ill-formed.
which says that the declaration is ill formed if the expression is in the identifier list. So this looks to me that success isn't part of expression. If this would be the case then
auto [iter, success] = myset.insert("Hello");
would only assign the inserted "Hello"
to iter
and success
would be what?!? The other way around it would violate the expression part. But it clearly compiles and runs so I must be missing something
Upvotes: 0
Views: 303
Reputation: 62613
I feel like you are getting confused by structured binding and if with initializer, but the simple way to look at it is to decompose them.
if (auto [a, b] = foo(); b)
Consists of two parts = first is initializer (auto [a, b] = foo()
) and second (b) is condition. It is exactly equivalent to
{
auto [a, b] = foo();
if (b)
}
In the example above, a
and b
would be deduced to whatever return type of foo
mandates, having nothing to do with if
condition below that.
Upvotes: 1
Reputation: 181068
which says that the declaration is ill formed if the expression is in the identifier list
It doesn't say that. It says that if expression uses any of the names in the identifier-list it is ill-formed. myset.insert("Hello")
doesn't do that so it is okay.
std::set::insert
returns a std::pair<std::set::iterator, bool>
where the std::set::iterator
marks the elements position and the bool
indicates if it was inserted or not. So auto [iter, success] = myset.insert("Hello")
captures that pair and sets iter
to the std::set::iterator
and success
to the bool
.
Upvotes: 5