Date: Wed, 13 Nov 2024 09:32:28 +0100
Il 12/11/2024 17:21, Thiago Macieira via Std-Proposals ha scritto:
> On Tuesday 12 November 2024 04:40:00 Pacific Standard Time Alberto Barbati via
> Std-Proposals wrote:
>> Hello everyone,
>>
>> I'd like to know if there's interest in introducing a way to selectively
>> ignore the effects of the [[deprecated]] attribute. Such a thing could
>> be useful in at least two scenarios:
>>
>> 1. You have an old API that is being replaced by a new API, but the new
>> API is written in terms of the old one (either temporarily or
>> because you plan to make the old API private in a future release,
>> without completely removing it)
>> 2. You have both a “safe” and an “unsafe” API and you want to encourage
>> the naïve user to use the safe one, while giving the possibility to
>> an experienced user to choose the unsafe API by declaring such
>> intent explicitly
> 3. Unit-testing the deprecated API itself.
>
> This case is the most common occurrence for us by far in Qt. We want to test
> this API but at the same time we don't want to use other deprecated API around
> it. That means disabling all deprecation warnings is not a good idea. Leaving
> them all as warnings is also noisy.
That's a very good use case. Thanks for pointing that out.
> We have a solution for this, which uses pragmas.
> https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/global/
> qcompilerdetection.h?h=v6.8.0#n1180
I have seen similar macros expanding to pragmas in several projects. For
example the Unreal Engine has a macro
PRAGMA_DISABLE_DEPRECATION_WARNINGS that is used 2500+ times in the
entire codebase. I take that as a hint that a standardized attribute
might be useful.
>> 1) Are attributes the right tool?
> I think so, because the code is syntactically correct.
>
>> 2) Should we use a different attribute (as "deprecated_ignorable" above)
>> or can/should we overload the existing [[deprecated]]?
> I don't think so. Either you have a reason to ignore a deprecation or you
> don't. The library author has already given you a heads up that this is either
> going away or is obsolete for some reason (or actively dangerous).
>> 3) The example above uses a string literal to tag the deprecation, so
>> that it can be referenced in [[ignore_deprecation]]. Alternatives and
>> variations could be considered, including, but not limited to,
>> identifiers instead of strings, multiple tags, etc.
> I think that is going too far. I'm not opposed to that, but in our experience,
> ignoring all deprecations for one statement or block suffices. You can always
> make shorter expressions that the ignoring should apply to and that's usually
> good code practice. Or use an IILE.
Ok, so no "fine grained" attribute. That's a good point.
>> 4) Should [[ignore_deprecation]] be applied only to compount statements
>> (as in the example above) or other statements/entities? Are there scopes
>> that could use the attribute that we would be missing (for example
>> function default arguments)?
> I'd like to see examples of where those would be useful and to see if there
> are other solutions to changing the content so it won't need the deprecated
> content in there.
>
> For example, if you've deprecated a type, then just don't: deprecate the
> constructors instead. If you've deprecated a function that returns the default
> value for this function, add a wrapper.
What I was thinking is that we might want to handle these cases:
[[deprecated]] struct Type1
{
};
struct Type2
{
[[deprecated]] Type2();
Type2(int);
};
void f1(Type1 x);
Type1 f2();
void f3(Type2 x = {});
For f1 and f3 we might put the ignoring attribute in the
parameter-declaration itself, but in the case of f2 I guess the only
good place is on the entire declaration. In any case, this shows we
might want to use the new attribute on other contexts beside statements
and need to specify the scope in those cases. For example, if we decide
to allow the attribute on the declaration, like this:
[ignore_deprecation]] Type1 f2()
{
// what about here?
}
then we need to specify whether the attribute is active or not in the
body of the function. The question is not moot, because we might also have:
[ignore_deprecation]] Type1 f2();
Type1 f2()
{
// what about here?
}
Of course, the only solution is to write a paper :)
ab
> On Tuesday 12 November 2024 04:40:00 Pacific Standard Time Alberto Barbati via
> Std-Proposals wrote:
>> Hello everyone,
>>
>> I'd like to know if there's interest in introducing a way to selectively
>> ignore the effects of the [[deprecated]] attribute. Such a thing could
>> be useful in at least two scenarios:
>>
>> 1. You have an old API that is being replaced by a new API, but the new
>> API is written in terms of the old one (either temporarily or
>> because you plan to make the old API private in a future release,
>> without completely removing it)
>> 2. You have both a “safe” and an “unsafe” API and you want to encourage
>> the naïve user to use the safe one, while giving the possibility to
>> an experienced user to choose the unsafe API by declaring such
>> intent explicitly
> 3. Unit-testing the deprecated API itself.
>
> This case is the most common occurrence for us by far in Qt. We want to test
> this API but at the same time we don't want to use other deprecated API around
> it. That means disabling all deprecation warnings is not a good idea. Leaving
> them all as warnings is also noisy.
That's a very good use case. Thanks for pointing that out.
> We have a solution for this, which uses pragmas.
> https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/global/
> qcompilerdetection.h?h=v6.8.0#n1180
I have seen similar macros expanding to pragmas in several projects. For
example the Unreal Engine has a macro
PRAGMA_DISABLE_DEPRECATION_WARNINGS that is used 2500+ times in the
entire codebase. I take that as a hint that a standardized attribute
might be useful.
>> 1) Are attributes the right tool?
> I think so, because the code is syntactically correct.
>
>> 2) Should we use a different attribute (as "deprecated_ignorable" above)
>> or can/should we overload the existing [[deprecated]]?
> I don't think so. Either you have a reason to ignore a deprecation or you
> don't. The library author has already given you a heads up that this is either
> going away or is obsolete for some reason (or actively dangerous).
>> 3) The example above uses a string literal to tag the deprecation, so
>> that it can be referenced in [[ignore_deprecation]]. Alternatives and
>> variations could be considered, including, but not limited to,
>> identifiers instead of strings, multiple tags, etc.
> I think that is going too far. I'm not opposed to that, but in our experience,
> ignoring all deprecations for one statement or block suffices. You can always
> make shorter expressions that the ignoring should apply to and that's usually
> good code practice. Or use an IILE.
Ok, so no "fine grained" attribute. That's a good point.
>> 4) Should [[ignore_deprecation]] be applied only to compount statements
>> (as in the example above) or other statements/entities? Are there scopes
>> that could use the attribute that we would be missing (for example
>> function default arguments)?
> I'd like to see examples of where those would be useful and to see if there
> are other solutions to changing the content so it won't need the deprecated
> content in there.
>
> For example, if you've deprecated a type, then just don't: deprecate the
> constructors instead. If you've deprecated a function that returns the default
> value for this function, add a wrapper.
What I was thinking is that we might want to handle these cases:
[[deprecated]] struct Type1
{
};
struct Type2
{
[[deprecated]] Type2();
Type2(int);
};
void f1(Type1 x);
Type1 f2();
void f3(Type2 x = {});
For f1 and f3 we might put the ignoring attribute in the
parameter-declaration itself, but in the case of f2 I guess the only
good place is on the entire declaration. In any case, this shows we
might want to use the new attribute on other contexts beside statements
and need to specify the scope in those cases. For example, if we decide
to allow the attribute on the declaration, like this:
[ignore_deprecation]] Type1 f2()
{
// what about here?
}
then we need to specify whether the attribute is active or not in the
body of the function. The question is not moot, because we might also have:
[ignore_deprecation]] Type1 f2();
Type1 f2()
{
// what about here?
}
Of course, the only solution is to write a paper :)
ab
Received on 2024-11-13 08:32:34