Date: Fri, 22 Sep 2023 06:09:44 +0100
On Thu, 21 Sept 2023, 22:38 Chris Gary via Std-Proposals, <
std-proposals_at_[hidden]> wrote:
> Like static_assert, except associated with the evaluation of a specific
> constraint.
>
> Errors generated by the following:
>
> `template< typename NoiseMakerT >
> requires( is_loud_v< NoiseMakerT > && is_annoying_v< NoiseMakerT > )
> void OnlyIfLoudAndAnnoying( const NoiseMakerT &N )
> {
> // etc..
> }`
>
> are immediately opaque when encountered in a diagnostic.
>
> Say, putting an "else" with a string literal after a "requires" could
> allow authors to spell out errors more precisely.
>
> `template< typename NoiseMakerT >
> requires( is_loud_v< NoiseMakerT > && is_annoying_v< NoiseMakerT > )
> else ( "The argument type is neither loud or annoying." )
> void OnlyIfLoudAndAnnoying( const NoiseMakerT &N )
> {
> // etc..
> }`
>
> Splitting it up can help to clarify where the situation is more
> complicated:
>
> `template< typename NoiseMakerT >
> requires( is_loud_v< NoiseMakerT > ) )
> else ( "The argument type is not loud." )
> requires( is_annoying_v< NoiseMakerT > )
> else ( "The argument type is not annoying." )
> void OnlyIfLoudAndAnnoying( const NoiseMakerT &N )
> {
> // etc..
> }`
>
>
> With concepts:
>
> `
> template< typename NoiseMakerT >
> concept LoudAndAnnoying = requires
> { is_loud_v<NoiseMakerT> && is_annoying_v<NoiseMakerT> }
> else
> { "The type is not loud and annoying."; };
>
> template< LoudAndAnnoying NoiseMakerT >
> else ( "The argument type is neither loud or annoying." )
> void OnlyIfLoudAndAnnoying( const NoiseMakerT &noisy )
> {
> // ...
> }`
>
> So, if violated:
>
> `class NotLoudOrAnnoying
> {
> // ...
> };
>
> void Fn()
> {
> NotLoudOrAnnoying oops{};
> OnlyIfLoudAndAnnoying( oops );
> }`
>
> This would print something like:
> "... error: The argument type is neither loud or annoying ..."
> "... error: The type is not loud and annoying ..."
>
> Instead of "a constraint was violated" or something else non-specific
> (read: eats time diagnosing the meaning of a diagnostic).
>
This seems like a poor implementation that should be improved. The compiler
should tell you which constraint was not satisfied.
> When printing out errors, the compiler would start from the deepest level
> of the call stack upwards.
> An option could be specified to limit error reports to only the first
> diagnostic.
>
> This can also nest into silly things, but it looks to be unambiguous:
>
> `template< typename NoiseMakerT >
> requires(
> requires
> { is_loud_v< NoiseMakerT > && is_annoying_v< NoiseMakerT > }
> else
> { "The argument type is neither loud or annoying." }
> )
> void OnlyIfLoudAndAnnoying( const NoiseMakerT &N )
> {
> // etc..
> }`
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
std-proposals_at_[hidden]> wrote:
> Like static_assert, except associated with the evaluation of a specific
> constraint.
>
> Errors generated by the following:
>
> `template< typename NoiseMakerT >
> requires( is_loud_v< NoiseMakerT > && is_annoying_v< NoiseMakerT > )
> void OnlyIfLoudAndAnnoying( const NoiseMakerT &N )
> {
> // etc..
> }`
>
> are immediately opaque when encountered in a diagnostic.
>
> Say, putting an "else" with a string literal after a "requires" could
> allow authors to spell out errors more precisely.
>
> `template< typename NoiseMakerT >
> requires( is_loud_v< NoiseMakerT > && is_annoying_v< NoiseMakerT > )
> else ( "The argument type is neither loud or annoying." )
> void OnlyIfLoudAndAnnoying( const NoiseMakerT &N )
> {
> // etc..
> }`
>
> Splitting it up can help to clarify where the situation is more
> complicated:
>
> `template< typename NoiseMakerT >
> requires( is_loud_v< NoiseMakerT > ) )
> else ( "The argument type is not loud." )
> requires( is_annoying_v< NoiseMakerT > )
> else ( "The argument type is not annoying." )
> void OnlyIfLoudAndAnnoying( const NoiseMakerT &N )
> {
> // etc..
> }`
>
>
> With concepts:
>
> `
> template< typename NoiseMakerT >
> concept LoudAndAnnoying = requires
> { is_loud_v<NoiseMakerT> && is_annoying_v<NoiseMakerT> }
> else
> { "The type is not loud and annoying."; };
>
> template< LoudAndAnnoying NoiseMakerT >
> else ( "The argument type is neither loud or annoying." )
> void OnlyIfLoudAndAnnoying( const NoiseMakerT &noisy )
> {
> // ...
> }`
>
> So, if violated:
>
> `class NotLoudOrAnnoying
> {
> // ...
> };
>
> void Fn()
> {
> NotLoudOrAnnoying oops{};
> OnlyIfLoudAndAnnoying( oops );
> }`
>
> This would print something like:
> "... error: The argument type is neither loud or annoying ..."
> "... error: The type is not loud and annoying ..."
>
> Instead of "a constraint was violated" or something else non-specific
> (read: eats time diagnosing the meaning of a diagnostic).
>
This seems like a poor implementation that should be improved. The compiler
should tell you which constraint was not satisfied.
> When printing out errors, the compiler would start from the deepest level
> of the call stack upwards.
> An option could be specified to limit error reports to only the first
> diagnostic.
>
> This can also nest into silly things, but it looks to be unambiguous:
>
> `template< typename NoiseMakerT >
> requires(
> requires
> { is_loud_v< NoiseMakerT > && is_annoying_v< NoiseMakerT > }
> else
> { "The argument type is neither loud or annoying." }
> )
> void OnlyIfLoudAndAnnoying( const NoiseMakerT &N )
> {
> // etc..
> }`
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2023-09-22 05:10:00