using followed by a
unary-expression that shall designate a modifiable
lvalue
Three separate conditions
The grammar alone would admit a great deal more than the wording allows.
§ expr.unary.general
unary-expression:
postfix-expression // a name, arr[i], obj.field, f(), p->m
++ cast-expression // ++x and --x are lvalues too
-- cast-expression
...postfix-expression is one of those alternatives, and it
is where a name, arr[i],
obj.field, a call f() and p->m
all live. A binary or conditional operator is not a unary-expression at
all:
x++ is a unary-expression — it arrives
through postfix-expression. But [§ expr.post.incr]/1 says
of its result:
The result is a prvalue.
Without shall designate a modifiable lvalue, auto [using x++, y] = f(); would
be well-formed.
An lvalue is not automatically modifiable. A const
object designates an lvalue, and the same clause catches it:
using id // a name
using *p // dereference
using arr[i] // subscript
using obj.field // member access
using (x) // parenthesised
using foo() // a function callAll six are unary-expressions, and all six should designate a modifiable lvalue.
Value category is a property of types, not of syntax — no grammar can express it. That is why the condition sits in the wording.