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.