P3817 — syntax

◀ back to the paper

What may follow using?

One unary-expression, with two conditions on it

The rule

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.

1. A unary-expression

§ 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:

using x + y          // not a unary-expression

2. An lvalue

x++ is a unary-expression — it arrives through postfix-expression. But [§ expr.post.incr]/1 says of its result:

The result is a prvalue.

using x++            // unary-expression, but a prvalue
using ++x            // this one IS an lvalue

Without shall designate a modifiable lvalue, auto [using x++, y] = f(); would be well-formed.

3. Modifiable

An lvalue is not automatically modifiable. A const object designates an lvalue, and the same clause catches it:

const int n = 0;
auto [using n, y] = f();     // n is an lvalue, but not a modifiable one

What that leaves

using id             // a name
using *p             // dereference
using arr[i]         // subscript
using obj.field      // member access
using (x)            // parenthesised
using foo()          // a function call

All 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.