Date: Sun, 29 Mar 2026 19:56:35 -0400
I'm having trouble understanding this thread. I still can't figure out the
answer to this question: does "Mandates:" allow defining a function as
deleted, or not?
Obviously, deleting a function is different from "Constraints". It's also
different from putting a static assertion in the body, because if you test
the validity of the call in an unevaluated context, e.g. using a
requires-expression, then in the deleted case, you see that it's not valid,
while in the case of a static assertion in the body, you see that it is
valid, but then get a hard error if you retry the same call in an evaluated
context.
The impression I've been given at another point in time was that
"Mandates:" is supposed to mean the latter behavior, but the library
wording doesn't outright say that, because we're not sure whether every
existing use of "Mandates:" is consistent with that. But, in the meantime,
I don't see the value of having a note that goes against the intent.
On Tue, Mar 24, 2026 at 3:23 AM Jonathan Wakely via Std-Proposals <
std-proposals_at_[hidden]> wrote:
>
>
> On Tue, 24 Mar 2026, 02:03 Jonathan Wakely, <cxx_at_[hidden]> wrote:
>
>>
>>
>> On Tue, 24 Mar 2026, 01:52 Jonathan Wakely, <cxx_at_[hidden]> wrote:
>>
>>>
>>>
>>> On Tue, 24 Mar 2026, 01:19 Halalaluyafail3, <luigighiron_at_[hidden]>
>>> wrote:
>>>
>>>> On Mon, Mar 23, 2026 at 9:06 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>>>> >
>>>> >
>>>> >
>>>> > On Tue, 24 Mar 2026, 00:34 Halalaluyafail3 via Std-Proposals, <
>>>> std-proposals_at_[hidden]> wrote:
>>>> >>
>>>> >> N5032 Section 16.3.2.4 "Detailed specifications"
>>>> [structure.specifications]
>>>> >> Paragraph 3:
>>>> >> > Mandates: the conditions that, if not met, render the program
>>>> ill-formed.
>>>> >>
>>>> >> Consider the following program:
>>>> >>
>>>> >> #include<bit>
>>>> >> decltype(std::bit_cast<void*>(^^::))x;
>>>> >>
>>>> >> Assume sizeof(void*)==sizeof(^^::) is true. Is this program
>>>> ill-formed? It would
>>>> >> seem that is the case, but existing implementations do not reject
>>>> this.
>>>> >
>>>> >
>>>> > You haven't instantiated the function template. The return type is
>>>> clearly void* so checking it without odr-using the function might works,
>>>> but is kinda dumb.
>>>> >
>>>> > In an uninstantiated template the condition is not necessarily
>>>> checked.
>>>>
>>>> I do not see how the current wording supports such an interpretation.
>>>> Note that
>>>> std::declval is specified using the mandate "This function is not
>>>> odr-used", is
>>>> this redundant and could be reduced to "false is true" similar to the
>>>> preconditions of std::unreachable?
>>>>
>>>
>>> Do you really think trying to draw general conditions from the wording
>>> for those two findings makes sense?
>>>
>>> Those tell functions cannot be evaluated ever in a valid program. There
>>> are no specializations of declval that are usable, ever. And any call to
>>> unreachable is a bug.
>>>
>>> Maybe they're special cases, which are not good examples of general
>>> purpose wording.
>>>
>>
>> If there's a defect here, it's that declval tries to use library
>> specification wording to say "this is only valid in unscented contexts"
>>
>
> Thanks autocorrect.
>
> They should say "unevaluated contexts".
>
>
> and we should have a special case in core wording just for this function.
>> But it didn't seem worth doing. We know what the spec means, and no
>> implementation has ever tried to implement declval as a deleted function.
>> That wouldn't work (and the spec doesn't say that an implementation must
>> pick *either* static assert *or* deleted functions, and use that
>> consistently for every Mandates).
>>
>> But that's ok because declval is a very weird special case.
>>
>> And unreachable is another weird special case, where wording that is
>> suitable for other functions is used a little strangely because we don't
>> have a good way to say "this is always a bug if evaluated".
>>
>> But that's not a general problem with the spec for Mandates.
>>
>>
>>
>>
>>>
>>>
>>>
>>>
>>>> >
>>>> >> The
>>>> >> example that follows the quoted text suggests that two possible
>>>> implementations
>>>> >> of mandates are static_asserts and deleted overloads. For uses of
>>>> mandates
>>>> >> outside of templates it seems like deleting the function is the only
>>>> way to
>>>> >> implement the mandate.
>>>> >
>>>> >
>>>> > Why?
>>>>
>>>> Since a static_assert failing there would immediately make the program
>>>> ill-formed. The only way to delay that until its use would be =delete.
>>>>
>>>> >
>>>> >> For uses of mandates inside of templates both options
>>>> >> would be valid, and create differences in the validity of programs
>>>> such the
>>>> >> program above. Was it intended for both possibilities to be valid,
>>>> or was it
>>>> >> intended for this program to assuredly be ill-formed or well-formed?
>>>> >
>>>> >
>>>> > I don't think it matters. If it mattered and the condition was
>>>> supposed to be SFINAE testable, it would use Constraints not Mandates.
>>>> >
>>>> > Why would you ever need the code above to be portable?
>>>>
>>>> Not to say that requiring this would be useful, but it seems like
>>>> intent is not
>>>> currently reflected in how Mandates is specified.
>>>>
>>>> >
>>>> >
>>>> >>
>>>> >> It seems like the uses of Mandates for the purposes of specifying
>>>> deletion could
>>>> >> be split up into a new "Deleted When" element, if the intent was to
>>>> require one
>>>> >> form be used. For example text_encoding uses mandates to require
>>>> CHAR_BIT==8,
>>>> >> that could realistically only be implemented as a deleted overload.
>>>> Would it
>>>> >> make sense to open a LWG issue for this?
>>>> >
>>>> >
>>>> > I don't see a defect here.
>>>> >
>>>> >
>>>> >
>>>>
>>> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
answer to this question: does "Mandates:" allow defining a function as
deleted, or not?
Obviously, deleting a function is different from "Constraints". It's also
different from putting a static assertion in the body, because if you test
the validity of the call in an unevaluated context, e.g. using a
requires-expression, then in the deleted case, you see that it's not valid,
while in the case of a static assertion in the body, you see that it is
valid, but then get a hard error if you retry the same call in an evaluated
context.
The impression I've been given at another point in time was that
"Mandates:" is supposed to mean the latter behavior, but the library
wording doesn't outright say that, because we're not sure whether every
existing use of "Mandates:" is consistent with that. But, in the meantime,
I don't see the value of having a note that goes against the intent.
On Tue, Mar 24, 2026 at 3:23 AM Jonathan Wakely via Std-Proposals <
std-proposals_at_[hidden]> wrote:
>
>
> On Tue, 24 Mar 2026, 02:03 Jonathan Wakely, <cxx_at_[hidden]> wrote:
>
>>
>>
>> On Tue, 24 Mar 2026, 01:52 Jonathan Wakely, <cxx_at_[hidden]> wrote:
>>
>>>
>>>
>>> On Tue, 24 Mar 2026, 01:19 Halalaluyafail3, <luigighiron_at_[hidden]>
>>> wrote:
>>>
>>>> On Mon, Mar 23, 2026 at 9:06 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>>>> >
>>>> >
>>>> >
>>>> > On Tue, 24 Mar 2026, 00:34 Halalaluyafail3 via Std-Proposals, <
>>>> std-proposals_at_[hidden]> wrote:
>>>> >>
>>>> >> N5032 Section 16.3.2.4 "Detailed specifications"
>>>> [structure.specifications]
>>>> >> Paragraph 3:
>>>> >> > Mandates: the conditions that, if not met, render the program
>>>> ill-formed.
>>>> >>
>>>> >> Consider the following program:
>>>> >>
>>>> >> #include<bit>
>>>> >> decltype(std::bit_cast<void*>(^^::))x;
>>>> >>
>>>> >> Assume sizeof(void*)==sizeof(^^::) is true. Is this program
>>>> ill-formed? It would
>>>> >> seem that is the case, but existing implementations do not reject
>>>> this.
>>>> >
>>>> >
>>>> > You haven't instantiated the function template. The return type is
>>>> clearly void* so checking it without odr-using the function might works,
>>>> but is kinda dumb.
>>>> >
>>>> > In an uninstantiated template the condition is not necessarily
>>>> checked.
>>>>
>>>> I do not see how the current wording supports such an interpretation.
>>>> Note that
>>>> std::declval is specified using the mandate "This function is not
>>>> odr-used", is
>>>> this redundant and could be reduced to "false is true" similar to the
>>>> preconditions of std::unreachable?
>>>>
>>>
>>> Do you really think trying to draw general conditions from the wording
>>> for those two findings makes sense?
>>>
>>> Those tell functions cannot be evaluated ever in a valid program. There
>>> are no specializations of declval that are usable, ever. And any call to
>>> unreachable is a bug.
>>>
>>> Maybe they're special cases, which are not good examples of general
>>> purpose wording.
>>>
>>
>> If there's a defect here, it's that declval tries to use library
>> specification wording to say "this is only valid in unscented contexts"
>>
>
> Thanks autocorrect.
>
> They should say "unevaluated contexts".
>
>
> and we should have a special case in core wording just for this function.
>> But it didn't seem worth doing. We know what the spec means, and no
>> implementation has ever tried to implement declval as a deleted function.
>> That wouldn't work (and the spec doesn't say that an implementation must
>> pick *either* static assert *or* deleted functions, and use that
>> consistently for every Mandates).
>>
>> But that's ok because declval is a very weird special case.
>>
>> And unreachable is another weird special case, where wording that is
>> suitable for other functions is used a little strangely because we don't
>> have a good way to say "this is always a bug if evaluated".
>>
>> But that's not a general problem with the spec for Mandates.
>>
>>
>>
>>
>>>
>>>
>>>
>>>
>>>> >
>>>> >> The
>>>> >> example that follows the quoted text suggests that two possible
>>>> implementations
>>>> >> of mandates are static_asserts and deleted overloads. For uses of
>>>> mandates
>>>> >> outside of templates it seems like deleting the function is the only
>>>> way to
>>>> >> implement the mandate.
>>>> >
>>>> >
>>>> > Why?
>>>>
>>>> Since a static_assert failing there would immediately make the program
>>>> ill-formed. The only way to delay that until its use would be =delete.
>>>>
>>>> >
>>>> >> For uses of mandates inside of templates both options
>>>> >> would be valid, and create differences in the validity of programs
>>>> such the
>>>> >> program above. Was it intended for both possibilities to be valid,
>>>> or was it
>>>> >> intended for this program to assuredly be ill-formed or well-formed?
>>>> >
>>>> >
>>>> > I don't think it matters. If it mattered and the condition was
>>>> supposed to be SFINAE testable, it would use Constraints not Mandates.
>>>> >
>>>> > Why would you ever need the code above to be portable?
>>>>
>>>> Not to say that requiring this would be useful, but it seems like
>>>> intent is not
>>>> currently reflected in how Mandates is specified.
>>>>
>>>> >
>>>> >
>>>> >>
>>>> >> It seems like the uses of Mandates for the purposes of specifying
>>>> deletion could
>>>> >> be split up into a new "Deleted When" element, if the intent was to
>>>> require one
>>>> >> form be used. For example text_encoding uses mandates to require
>>>> CHAR_BIT==8,
>>>> >> that could realistically only be implemented as a deleted overload.
>>>> Would it
>>>> >> make sense to open a LWG issue for this?
>>>> >
>>>> >
>>>> > I don't see a defect here.
>>>> >
>>>> >
>>>> >
>>>>
>>> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
-- *Brian Bi*
Received on 2026-03-29 23:56:53
