On Mon, 2017-11-06 at 03:15 +0200, Peter Dimov via Boost wrote:
Now that there are standard feature-testing macros (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0096r5.html) that are being implemented by at least g++ and clang++, would it perhaps make sense for us to reevaluate our decision to provide negative macros in Boost.Config and start defining the standard feature macros instead on the compilers that don't support them?
I think it would be better to provide macros like how the Fit library does: https://github.com/pfultz2/Fit/blob/master/include/fit/config.hpp#L93 The macros are always defined, but can be easily overridden. So if a compiler has a bug with the feature or is lying, then the user can easily build by adding `-DBOOST_HAS_FEATURE=...` to compilation to enable or disable the feature in boost. The current setup this is not possible because we always write `#ifdef BOOST_NO_FEATURE` and there is no way to express that the macro should be left undefined even if Boost.Config thinks it should be defined. Instead we should be writing `#if !BOOST_HAS_FEATURE` and Boost.Config defines it 0 or 1 if it hasn't already been defined by the user.
This would seem to require less maintenance, and the feature macro can be used without waiting for Boost.Config to add it.
For a concrete example, let's take noexcept in function types. This is __cpp_noexcept_function_type, and is implemented by g++ 7, clang 4, clang 5 (in C++17 mode), and apparently in the latest VS2017 preview.
noexcept function pointers break Boost.Bind, and to fix it, I need to add overloads for them, but only if they are implemented, otherwise the overloads would be an error.
With the feature macro, I can just #ifdef __cpp_noexcept_function_type and it will immediately work on g++ and clang++ and all compilers that don't support noexcept function types will still work. Only msvc would need to be fixed in some way.
With our traditional approach, I would need to request the addition of BOOST_NO_CXX17_NOEXCEPT_FUNCTION_TYPE, wait for it to be added and to be present on every compiler except the latest ones (which requires changes throughout Boost.Config), and only then be able to use #ifndef BOOST_NO_CXX17_NOEXCEPT_FUNCTION_TYPE. (Then wait for it to be merged to master before merging my changes to master.)
Of course, boost shouldn't define `__cpp_noexcept_function_type`, but it could define `BOOST_FEATURE_NOEXCEPT_FUNCTION_TYPE`(or whatever mapping we want to have from sd-6 macros to boost macros). Using the scheme above, Boost.Bind could define it if it hasn't already been defined by Boost.Config or the user. So simply doing: #ifndef BOOST_FEATURE_NOEXCEPT_FUNCTION_TYPE #ifdef __cpp_noexcept_function_type #define BOOST_FEATURE_NOEXCEPT_FUNCTION_TYPE 1 #else #define BOOST_FEATURE_NOEXCEPT_FUNCTION_TYPE 0 #endif #endif This way Boost.Bind can start using that feature while it waits for it to be integrated in Boost.Config, and then it can remove the macro definition above once its integrated into Boost.Config. This does have a potential problem if two libraries decide to define the macro in different ways, but this should only exists until its integrated into Boost.Config.