- Notifications
You must be signed in to change notification settings - Fork 8
Description
Full name of submitter (unless configured in github; will be published with the issue): Jiang An
Reference (section label): [dcl.attr.assume]
Link to reflector thread (if any):
Issue description:
Given the following well-formed program, removing the assumption statement renders it ill-formed (Godbolt link). This is because [[assume]] makes its condition potentially evaluated, and every potentially evaluated occurrence of next() modifies the state of overload resolution.
template<int N> struct reader { friend auto flag(reader); }; template<int N> struct setter { friend auto flag(reader<N>) {} }; template<int N = 0, auto DifferenceMaker = [] {}> consteval int next() { if constexpr (requires { flag(reader<N>{}); }) { return next<N + 1>(); } else { (void) setter<N>{}; return N; } } int main() { static_assert(next() == 0); [[assume(true || next())]]; static_assert(next() == 2); }The example also shows that Note 5 in [dcl.attr.grammar] is incorrect for [[assume]], as removing all instances of [[assume]] can make a well-formed program (using stateful metaprogramming) ill-formed or have different semantics.
The original direction of CWG2118 would reject this program. But CWG2118 seems inactive and possibly NAD, as arcane things are (and will be) introduced later:
- Unevaluated lambda expression whose type is difference between occurrences (introduced in P0315R4), and
- The compile-time ticket counter in P2996.
Suggested resolution:
Perhaps we should say "unless otherwise specified" in the note, and say that some semantic aspects of [[assume]] are not ignorable.
Maybe we can resolve such contradiction editorially because the ignorability is only mentioned in a note.