[config] Positive feature macros, r2
I'd like to revisit the topic of Boost.Config feature macros, specifically that in my opinion, positive feature macros (BOOST_CXX17_FEATURE) make more sense than negative macros (BOOST_NO_CXX17_FEATURE) in the current environment. Negative macros made sense in the past when they signified bugs and deficiencies in the compiler as measured against a static standard. Nowadays, the standard, such as it is, is in constant motion and macros indicate merely a current state of development for both the compiler and the standard. The arguments for positive macros are the same as last time: - adding a new negative macro requires changes to all legacy compilers that do not and will never implement the feature; a positive macro only requires changes to active compilers. - positive macros are a better match for the standard feature macros, which are positive. When we see a standard feature macro being set, we typically would set ours as well. This means that the amount of changes required to add a new macro is further reduced; we only need to touch compiler-specific config files if the compiler either does not implement feature macros, or sets them incorrectly (in our considered opinion.) TL;DR we should switch to positive feature macros in Boost.Config, and delaying this switch just accumulates more unnecessary code in Boost.Config.
On 01/25/18 19:51, Peter Dimov via Boost wrote:
I'd like to revisit the topic of Boost.Config feature macros, specifically that in my opinion, positive feature macros (BOOST_CXX17_FEATURE) make more sense than negative macros (BOOST_NO_CXX17_FEATURE) in the current environment.
Negative macros made sense in the past when they signified bugs and deficiencies in the compiler as measured against a static standard. Nowadays, the standard, such as it is, is in constant motion and macros indicate merely a current state of development for both the compiler and the standard.
The arguments for positive macros are the same as last time:
- adding a new negative macro requires changes to all legacy compilers that do not and will never implement the feature; a positive macro only requires changes to active compilers.
- positive macros are a better match for the standard feature macros, which are positive. When we see a standard feature macro being set, we typically would set ours as well. This means that the amount of changes required to add a new macro is further reduced; we only need to touch compiler-specific config files if the compiler either does not implement feature macros, or sets them incorrectly (in our considered opinion.)
TL;DR we should switch to positive feature macros in Boost.Config, and delaying this switch just accumulates more unnecessary code in Boost.Config.
My opinion hasn't changed since the last discussion - if we move to positive macros then please convert all existing macros as well. I wouldn't want to remember which one is positive or negative.
TL;DR we should switch to positive feature macros in Boost.Config, and delaying this switch just accumulates more unnecessary code in Boost.Config.
My opinion hasn't changed since the last discussion - if we move to positive macros then please convert all existing macros as well. I wouldn't want to remember which one is positive or negative.
+1 on that. I've been mostly silent on this because: * Other folks have expressed what I feel as well (but I'm notoriously slow to embrace change, so treat that with a pinch of salt). * The number of new macros has slowed very significantly in recent years. * The number of actively developed compilers is very much lower than in the past. * I see no great gain for *users* of the library. * We currently separate standardized features which are all BOOST_NO_* and vendor extensions which are all BOOST_HAS_*. For compilers that are effectively "dead", we could just add a catch all macro: #define BOOST_OBSOLETE_COMPILER year and then set all macros past "year" in suffix.hpp, so if we had #define BOOST_OBSOLETE_COMPILER 2011 Then set all BOOST_NO_CXX11_* macros and later in suffix.hpp and job done. John. --- This email has been checked for viruses by AVG. http://www.avg.com
John Maddock wrote:
For compilers that are effectively "dead", we could just...
In principle, what I suggest is perfectly doable with negative macros too. We put #if !defined(__cpp_foo) || __cpp_foo < 201400 # define BOOST_NO_CXX14_FOO #endif in prefix.hpp, then in the compiler-specific configs #undef the macros instead of setting them. The only reason to prefer positivity is because this way of doing things is what comes naturally when positive macros are used.
From user point of view, I've always felt that
#ifdef BOOST_CXX17_FEATURE
// use c++17 feature
#endif
reads better than the inverted test, but that's probably a matter of taste.
(This also degrades gracefully if one forgets the
AMDG On 01/25/2018 09:51 AM, Peter Dimov via Boost wrote:
I'd like to revisit the topic of Boost.Config feature macros, specifically that in my opinion, positive feature macros (BOOST_CXX17_FEATURE) make more sense than negative macros (BOOST_NO_CXX17_FEATURE) in the current environment.
Negative macros made sense in the past when they signified bugs and deficiencies in the compiler as measured against a static standard. Nowadays, the standard, such as it is, is in constant motion and macros indicate merely a current state of development for both the compiler and the standard.
The arguments for positive macros are the same as last time:
- adding a new negative macro requires changes to all legacy compilers that do not and will never implement the feature; a positive macro only requires changes to active compilers.
- positive macros are a better match for the standard feature macros, which are positive. When we see a standard feature macro being set, we typically would set ours as well. This means that the amount of changes required to add a new macro is further reduced; we only need to touch compiler-specific config files if the compiler either does not implement feature macros, or sets them incorrectly (in our considered opinion.)
I'm opposed to this, as I believe that it simply creates pointless churn. I consider the proposed benefits to be utterly insignificant. In Christ, Steven Watanabe
Steven Watanabe wrote:
I'm opposed to this, as I believe that it simply creates pointless churn. I consider the proposed benefits to be utterly insignificant.
It does not bother you that when adding a feature macro one needs to remember to add it to all compiler configurations, live or dead? And that if one forgets nobody is any the wiser? It does not bother you that we can't just add #if defined(__cpp_foo) && __cpp_foo >= 201400 # define BOOST_CXX14_FOO #endif in one place and have it mostly work, instead of touching O(N) files?
On Jan 25, 2018, at 11:39 AM, Peter Dimov via Boost
wrote: Steven Watanabe wrote:
I'm opposed to this, as I believe that it simply creates pointless churn. I consider the proposed benefits to be utterly insignificant.
It does not bother you that when adding a feature macro one needs to remember to add it to all compiler configurations, live or dead? And that if one forgets nobody is any the wiser?
It does not bother you that we can't just add
#if defined(__cpp_foo) && __cpp_foo >= 201400 # define BOOST_CXX14_FOO #endif
in one place and have it mostly work, instead of touching O(N) files?
I think it would be better to define the positive macros like this: #ifndef BOOST_CXX14_FOO #if defined(__cpp_foo) && __cpp_foo >= 201400 # define BOOST_CXX14_FOO 1 #else # define BOOST_CXX14_FOO 0 #endif #endif This way: - We get a warning when checking the macro when it hasn’t been defined properly - The user can easily override the value with `-DBOOST_CXX14_FOO=0` during compilation because a feature turns out to be buggy.
"P F" wrote:
#if defined(__cpp_foo) && __cpp_foo >= 201400 # define BOOST_CXX14_FOO #endif
I think it would be better to define the positive macros like this:
#ifndef BOOST_CXX14_FOO #if defined(__cpp_foo) && __cpp_foo >= 201400 # define BOOST_CXX14_FOO 1 #else # define BOOST_CXX14_FOO 0 #endif #endif
This way:
- We get a warning when checking the macro when it hasn’t been defined properly - The user can easily override the value with `-DBOOST_CXX14_FOO=0` during compilation because a feature turns out to be buggy.
As written, this does not allow the latter. The general case is: // prefix.hpp: #if defined(__cpp_foo) && __cpp_foo >= 201400 # define BOOST_CXX14_FOO #endif // compiler/bar.hpp: #if __BAR_VERSION__ >= 12 && __BAR_VERSION__ < 18 // have foo, don't have feature macros yet # define BOOST_CXX14_FOO #endif #if __BAR_VERSION__ == 21 && __cplusplus >= 201700 // bar++ version 21 has a bug in foo in -std=c++17 mode # undef BOOST_CXX14_FOO #endif If you define to 0 or 1 in prefix.hpp, the information of whether the user overrode is lost, and the compiler-specific config can still stomp over the user define. I think that Boost.Config already offers a few mechanisms for the user to override, they're not as simple as a define on the command line though.
AMDG On 01/26/2018 08:30 AM, Peter Dimov via Boost wrote:
As written, this does not allow the latter. The general case is:
// prefix.hpp:
#if defined(__cpp_foo) && __cpp_foo >= 201400 # define BOOST_CXX14_FOO #endif
// compiler/bar.hpp:
#if __BAR_VERSION__ >= 12 && __BAR_VERSION__ < 18 // have foo, don't have feature macros yet # define BOOST_CXX14_FOO #endif
#if __BAR_VERSION__ == 21 && __cplusplus >= 201700 // bar++ version 21 has a bug in foo in -std=c++17 mode # undef BOOST_CXX14_FOO #endif
If you define to 0 or 1 in prefix.hpp, the information of whether the user overrode is lost, and the compiler-specific config can still stomp over the user define.
Just apply the defaults after the compiler specific configuration instead of before, and there's no problem. In Christ, Steven Watanabe
On 1/25/2018 11:51 AM, Peter Dimov via Boost wrote:
I'd like to revisit the topic of Boost.Config feature macros, specifically that in my opinion, positive feature macros (BOOST_CXX17_FEATURE) make more sense than negative macros (BOOST_NO_CXX17_FEATURE) in the current environment.
Negative macros made sense in the past when they signified bugs and deficiencies in the compiler as measured against a static standard. Nowadays, the standard, such as it is, is in constant motion and macros indicate merely a current state of development for both the compiler and the standard.
The arguments for positive macros are the same as last time:
- adding a new negative macro requires changes to all legacy compilers that do not and will never implement the feature; a positive macro only requires changes to active compilers.
- positive macros are a better match for the standard feature macros, which are positive. When we see a standard feature macro being set, we typically would set ours as well. This means that the amount of changes required to add a new macro is further reduced; we only need to touch compiler-specific config files if the compiler either does not implement feature macros, or sets them incorrectly (in our considered opinion.)
TL;DR we should switch to positive feature macros in Boost.Config, and delaying this switch just accumulates more unnecessary code in Boost.Config.
I agree with Peter, basically because it makes for much more readable code as well as the reason Peter gives, because we do not have to consistently be changing config headers just to say that something X does not support some new Y. I understand Steven's comment that this is much churn for seemingly little, but when one realizes that the design seems now wrong, even just syntactically, then churn is justified IMO. I think we can support the _NO_ forms for a few releases, while deprecating them, while we add any new macros as positive features, and basically tell library developers to change their code to use the new positive macros. I do agree that all our _NO_ macros need to have a positive equivalent whenever the _NO_ macro is for a general feature rather than for specific compiler weaknesses ( I realize this is judgmental ). Telling end-user to change their own code to use the positive form is a PITA, but I would still do it. I feel strongly that Peter is right and the negative forms we have propagated is the wrong syntactical design for config as C++ goes forward with new features and new releases. We might also be able to write some code, Python or C++, which searches some set of files for all the current config _NO_ macros being used and prints the file name, line number, and line in some sort of summary file. We could do this as an aid both for library developers and end-user switching from the _NO_ form to the proposed positive form of any given config macro. I know when I programmed cxxd I purposely wanted to provide my own cxxd macros as positive things rather than mimic the _NO_ form of the config macros, even when heavily using config underneath to implement cxxd. So I know people may consider me biased because of that, but that is still the way I see this issue as far as the _NO_ forms are concerned. Of course if we decide to follow Peter's suggestion and make the change, it is, as always, who is going to do the work. It would be ridiculous to lay this all on John. I am volunteering to help if needed, and I imagine Peter would also, so it would be a matter of finding those people with the time to make this happen if we decided to do it.
Of course if we decide to follow Peter's suggestion and make the change, it is, as always, who is going to do the work. It would be ridiculous to lay this all on John. I am volunteering to help if needed, and I imagine Peter would also, so it would be a matter of finding those people with the time to make this happen if we decided to do it.
I think that since this is effectively Config.v2 we're talking about here, and since I have absolutely no time for this anyway, then if it's decided that this is the way forward, it would be better if the maintenance baton were handed on to someone else at this point: BTW this is absolutely not me "chucking my toys out of the pram", just a realistic assessment that I have neither time nor much inclination for this at this time. I would obviously try and provide constructive criticism / help as I can. I'm also frankly amazed that the design has worked as well as it has for so long - there's an awful lot of hard one knowledge encoded in the Config headers, and I hope that can be retained. BTW, if we're looking at a redesign, and potentially a lot of churn in client code, I think I'd like to see at least a mini-review before any change: Boost.Config is so central to everything and the effects of substantive change potentially so damaging if we get wrong, that some extra-special caution is required in this particular case IMO. Best, John. --- This email has been checked for viruses by AVG. http://www.avg.com
On 1/26/2018 1:03 PM, John Maddock via Boost wrote:
Of course if we decide to follow Peter's suggestion and make the change, it is, as always, who is going to do the work. It would be ridiculous to lay this all on John. I am volunteering to help if needed, and I imagine Peter would also, so it would be a matter of finding those people with the time to make this happen if we decided to do it.
I think that since this is effectively Config.v2 we're talking about here, and since I have absolutely no time for this anyway, then if it's decided that this is the way forward, it would be better if the maintenance baton were handed on to someone else at this point: BTW this is absolutely not me "chucking my toys out of the pram", just a realistic assessment that I have neither time nor much inclination for this at this time. I would obviously try and provide constructive criticism / help as I can. I'm also frankly amazed that the design has worked as well as it has for so long - there's an awful lot of hard one knowledge encoded in the Config headers, and I hope that can be retained.
I hope you do realize that my own comments are not even remotely a criticism as to how well config has worked or your incredible job at keeping it as good as it has been. Nor do I think, from what I know of config, that the actual design logic of config has to change. But it may be that I am not seeing the many complications that you foresee.
BTW, if we're looking at a redesign, and potentially a lot of churn in client code, I think I'd like to see at least a mini-review before any change: Boost.Config is so central to everything and the effects of substantive change potentially so damaging if we get wrong, that some extra-special caution is required in this particular case IMO.
I hear that. I think that is why Peter's suggestion, which may have been considered in general before as an idea, has never seriously been considered in actuality. Getting it right must be perfect, else the rest of Boost will be greatly messed up.
Best, John.
John Maddock wrote:
BTW, if we're looking at a redesign, and potentially a lot of churn in client code, I think I'd like to see at least a mini-review before any change: Boost.Config is so central to everything and the effects of substantive change potentially so damaging if we get wrong, that some extra-special caution is required in this particular case IMO.
This has gone quite a bit further than what I had in mind. I did not intend a redesign or churn in existing client code, but merely (a) for new macros being added to be of the positive variety and (b) to take advantage of the standard feature macros so that our future maintenance work is minimized. Of course for consistency we would probably add positive macros to match our negative ones, but I did not envisage removing the existing macros or necessarily changing any existing code. I can see why one would think, well, if we're to change things, why not change them even more. Perhaps we should. It's just not what I proposed, or propose. To put it in the most succinct terms, my goal was minimization of the necessary diffs required to support a new feature or a new compiler version. Redesigning things from the ground up is rather out of scope.
On Thu, Jan 25, 2018 at 11:51 AM, Peter Dimov wrote:
TL;DR we should switch to positive feature macros in Boost.Config, and delaying this switch just accumulates more unnecessary code in Boost.Config.
I'm for this. And happy to help with the changes to both Config and all individual libraries. Glen
participants (7)
-
Andrey Semashev
-
Edward Diener
-
Glen Fernandes
-
John Maddock
-
P F
-
Peter Dimov
-
Steven Watanabe