[PATCH] assert: Support assert as variadic macro for C++26 [PR27276]
Jonathan Wakely
jwakely@redhat.com
Thu Feb 5 15:57:11 GMT 2026
On Thu, 5 Feb 2026 at 15:48, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On Thu, 5 Feb 2026 at 15:40, Tomasz Kaminski <tkaminsk@redhat.com> wrote:
> >
> >
> >
> > On Thu, Feb 5, 2026 at 4:36 PM Florian Weimer <fweimer@redhat.com> wrote:
> >>
> >> * Tomasz Kamiński:
> >>
> >> > +# if __ASSERT_VARIADIC
> >> > +# define assert(...) \
> >> > + ((__VA_ARGS__) \
> >> > + ? (void)(1 ? 1 : bool(__VA_ARGS__)) \
> >> > + : __assert_fail (#__VA_ARGS__, __ASSERT_FILE, __ASSERT_LINE, \
> >> > + __ASSERT_FUNCTION))
> >>
> >> Doesn't this evaluate __VA_ARGS__ multiple times?
> >
> > I got the same question initially when I saw this solution, but
> > the second bool(__VA_ARGS) is in the false branch of the ternary:
> > 1 ? 1 : bool(__VA_ARGS__)
> > So it is never evaluated.
>
> Right, it's never evaluated, it's only there to enforce that
> __VA_ARGS__ expands to a single expression, because bool(x,y) is
> ill-formed.
Maybe it needs a comment explaining the logic, and saying "Be careful
when touching this, every piece of it is load-bearing!" ;-)
The key pieces are that this relies on the "contextually converted to
bool" rule <https://wg21.link/conv.general#4>
(__VA_ARGS__) ? expr : __assert_fail(...);
This is a "weaker" form of conversion than casting to bool, and so
prevents scoped enum types from being asserted on (they aren't
convertible to integers, so they shouldn't be implicitly converted to
'true;' or 'false' in assertions).
And as explained above, the (void)(1 ? 1 : bool(__VA_ARGS__)) part has
no side effects but ensures that assert(x, y) is ill-formed, at least
when NDEBUG is not defined.
More information about the Libc-alpha
mailing list