Date: Sun, 08 Jan 2023 16:26:58 -0500
Right now, the specification of `decltype(expr)` have two mutually distinct behaviors:
1. id expr or member access expr: refers to the type of the declaration that introduced the id expr.
2. otherwise: refers to the type and value category of expr, if expr were to be evaluated.
Both are distinct enough operations, but they still use exactly the same syntax, and interpretation rely on semantic properties of `expr`. AFAIK, there doesn't seem to be any generic context where we could want a single `decltype(expr)` be interpreted in one way or the other depending on the value or type of a template parameter. Either we force behavior 2 with `decltype((expr))`, otherwise we 'hope' that other developers get that we intended behavior 1 if `expr` appears to be, say a member access expression `v.m1`. But, suppose at some point we refactor code, make the member private and define an accessor function instead, then the interpretation of `decltype(v.get_m1())` will most likely have changed of meaning, without any compiler diagnostic.
Another oddity about decltype is that behavior 2 is achieved by use of "syntactic cleverness". There's nothing special about the extra pair of parentheses: if we want to force behavior 2 we *may* use `decltype((expr))`, but we may as well write `decltype(0, expr)`, or `decltype(*&expr)` (if expr is an id expression or member access). Considering that behavior 2 accounts for most uses of `decltype`, I think it deserves to be expressed in a form which is 'non compound' and free of syntactic cleverness.
In ideal, at the time decltype keyword got introduced, I think we should have instead introduced two keywords (say `exprtype` and `decltype`), each in one-one relationship with their respective behaviors:
1. `decltype(expr)`: this would fail to compile if `expr` is not an id expression, member access expression, structured binding, etc. ie, this guarantee behavior 1 or program is ill formed.
2. `exprtype(expr)`: this would be identical to the current interpretation of `decltype((expr))`; ie, this is behavior 2.
We can't change the interpretation of `decltype(expr)` anymore.
So I propose to introduce two new builtin constructs with the semantics as described just above:
1. `declaration_type(expr)`
2. `exprtype(expr)`
Note: `declaration_type` is a placeholder name for now.
Cheers,
Julien V.
-- Julien Villemure
Sent from my Android device with K-9 Mail.
1. id expr or member access expr: refers to the type of the declaration that introduced the id expr.
2. otherwise: refers to the type and value category of expr, if expr were to be evaluated.
Both are distinct enough operations, but they still use exactly the same syntax, and interpretation rely on semantic properties of `expr`. AFAIK, there doesn't seem to be any generic context where we could want a single `decltype(expr)` be interpreted in one way or the other depending on the value or type of a template parameter. Either we force behavior 2 with `decltype((expr))`, otherwise we 'hope' that other developers get that we intended behavior 1 if `expr` appears to be, say a member access expression `v.m1`. But, suppose at some point we refactor code, make the member private and define an accessor function instead, then the interpretation of `decltype(v.get_m1())` will most likely have changed of meaning, without any compiler diagnostic.
Another oddity about decltype is that behavior 2 is achieved by use of "syntactic cleverness". There's nothing special about the extra pair of parentheses: if we want to force behavior 2 we *may* use `decltype((expr))`, but we may as well write `decltype(0, expr)`, or `decltype(*&expr)` (if expr is an id expression or member access). Considering that behavior 2 accounts for most uses of `decltype`, I think it deserves to be expressed in a form which is 'non compound' and free of syntactic cleverness.
In ideal, at the time decltype keyword got introduced, I think we should have instead introduced two keywords (say `exprtype` and `decltype`), each in one-one relationship with their respective behaviors:
1. `decltype(expr)`: this would fail to compile if `expr` is not an id expression, member access expression, structured binding, etc. ie, this guarantee behavior 1 or program is ill formed.
2. `exprtype(expr)`: this would be identical to the current interpretation of `decltype((expr))`; ie, this is behavior 2.
We can't change the interpretation of `decltype(expr)` anymore.
So I propose to introduce two new builtin constructs with the semantics as described just above:
1. `declaration_type(expr)`
2. `exprtype(expr)`
Note: `declaration_type` is a placeholder name for now.
Cheers,
Julien V.
-- Julien Villemure
Sent from my Android device with K-9 Mail.
Received on 2023-01-08 21:27:08