The C++ library and language is now evolving at an unprecedented rate. This rapid evolution creates issues for boost library maintainers and users. For maintainers keeping libraries operating with new C++ features and types requires significant effort. The user community has diverse needs including support for older C++ versions as well as newer standards. In addition, whole libraries from Boost have been adopted into the standard reducing the overall value of some Boost libraries.
As of this writing (May 2018) a poll of C++Now participants demonstrated majority C++11 usage with significant C++14 and C++17 usage.
The following outlines some of the issues and potential solutions discussed during LIAW 2017 and 2018.
New C++ language and library features are being added rapidly. C++17 added at least 100 new features and C++20 features already voted into the standards (aka concepts) track will make large changes as well.
The issue of Boost libraries tracking this standard is only going to increase over time. There’s at least a few different scenarios for impacts to boost libraries including:
- drop in replacement: library is now in std (addressof, enable_if)
- partial replacement: library is in std, but has differences (thread, shared_ptr)
- library is in std, but quite different (date_time)
- library replaced by a langauge feature (foreach, lambda)
- library that references a type (like shared_ptr) changed in std
The list of new library types since C++11 in the standard is long including std::optional, std::variant, std::shared_ptr, std::tuple, etc. Many of these ‘vocabulary types’ are derived from similar boost types creating a tension for library authors about what to prefer.
Users that are writing programs with C++11 and beyond will use these types and expect boost libraries to use and support them. It is acknowledged that some users will use boost components instead of std components due to feature extensions offered by boost.
Maintaining a library that supports both boost and std types is complex and time consuming. Also, some users would prefer a smaller version of boost that drops boost libraries now provided in the standard including: any, atomic, bind, endian, filesystem, lexical_cast, optional, regex, system, thread, and variant. This list will grow in C++20 and beyond.
A particularly sticky case is boost::shared_ptr dependencies.
As a concrete example, boost.date-time users boost::shared_ptr for the management of time zone types. With most users at C++11 it would make more sense for this interface to support std::shared_ptr instead.
Note this decision has some negative consequences for users of boost::shared_ptr. In particular it means they cannot use other varations of shared_ptr that may eventually get into the standard. Thanks to Glen Ferandes pointed out this issue.
So perhaps the better advice is for library authors to allow templatization on the pointer return type – this would need to be prototyped.
Libraries using shared_ptr in interface include: algorithm, asio, beast, contract, date-time, dll, exception, geometry, get_pointer, graph, iterator, locale, log, mpi, pointer_cast, process, program_options, property_map, python, serialization, signals, signals2, interprocess, iostreams, serialization, shared_container, spirit, startechart, thread, type_erasure, type_index, uuid, wave.
Users of strings in c++17 would like to utilize string view. Potentially impacted libraries include string_algo, tokenizer, regex.
This section needs work!
The primary example here is std::auto_ptr. Modern compilers in C++17 and higher versions now warn about auto_ptr being deprecated. Having boost libraries trigger compiler warnings lowers quality for users.
A number of libraries use auto_ptr including asio, date-time, python, program_options, iostreams, assign, ptr_container, locale, and serialization.
The following libraries have already worked around this issue as of 1.67 using boost.config macros: date-time, iostreams, ptr_container, python.
The fix for auto_ptr is relatively straight forward. Change to std::unique_ptr for c++11 mode and beyond.
Some language features such as concepts and constexpr can radically impact the interfaces and construction of libraries.
Libraries supporting constexpr in interfaces are not compatible with pre C++11 versions of C++. For some types of libraries supporting constexpr interfaces is highly desired since it leads to higher runtime performance due to pre-computed compile time values.
C++17 guarantees construction of header defined static values This is an extremely valuable guaranteed for authors desiring header only implementations that need statically defined data.
date-time is an example of a library that could trivially be made header only due to this guarantee.
Deduction guides can simplify a user interface to a library. This is C++17 and beyond only. As an example from https://github.com/tvaneerd/cpp17_in_TTs/blob/master/ALL_IN_ONE.md
//c++14 pair<int, string> is1 = pair<int, string>(17, "hello"); auto is2 = std::pair<int, string>(17, "hello"); auto is3 = std::make_pair(17, string("hello")); auto is4 = std::make_pair(17, "hello"s); //c++17 pair<int, string> is1 = pair(17, "hello"); auto is2 = pair(17, "hello"); // !! pair<int, char const *> auto is3 = pair(17, string("hello")); auto is4 = pair(17, "hello"s);
Note that without deduction guides for many of the boost container type libraries there is a risk of users used to using shortened names from std:: will get surprising results with boost.
Concepts will radically transform the construction of template libraries. Modules will also begin to transform library development as well. While the timing and details of these features are still being debated all expectations are that they will arrive and boost will need to respond.
- Maintaining boost libraries is difficult to start.
- No one will want to be a boost author if mired in c++98
- Supporting legacy C++ compilers is a burden
- #ifdef for all these c++ versions is painful and reduces maintainability
- Limited community maintenance resources are already strained
- let things continue to fester
- provide no guidance
- Define standards and tools for developers to move to newer C++ versions
- boostNN (aka boost17) namespace could be used to delinate libraries
- individual authors/community support teams decide when to drop
The C++ standard is now on 3 year cycles. This proposal would put boost on a similar schedule. The library collection would split into 2 major release streams: LTS and advanced. LTS would support users compiling in older versions of c++ and recieve minimal maintenance. Advanced would track closer to the latest c++ standard. Every 3 years advanced will drop support for a six year old version of the standard and LTS will drop support for a 9 year old c++ version.
Note that this proposal is a suggestion for best practice and does not override the library author perogative to support a wider range of c++ versions.
This distribution of boost would support users with legacy c++ needs. In general the following would apply:
- will continue to maintain libraries in later c++ versions (any, variant, etc)
- no new libraries added to LTS unless explicitly requested by library author
- critical bug fixes only
- approximately one release annually
- tested only against earlier c++ versions and compilers
The first LTS target would support C++98/03 users and would coorespond would be the first 2019 release and would be the continuation of the boost1_xx series.
The advanced version will drop support for older C++ language versions freeing library authors from maintaining backward compatibility. The advanced version of boost will trail the standard by approximately 2 standard releases. So the first advanced version would be Boost 11.
Overall the following applies:
- no testing of older/dropped c++versions
- no expectation of library support for older c++versions
- removal of boost libraries available in std
- adoption of latest c++ standard features
- removal of older compilers from the tests that do not support newer c++versions
- expect library interface breaking changes as libraries are updated for new std types
- removal of version 1 libraries
For some libraries with extensive changes due to standard impacts breaking changes may be done by creating a version 2 of the library. This already has precedence in boost, but may happen more now that the standard is evolving quickly.
For some libraries in the advanced release it may make sense to provide a gradual transtion by forwarding to std:: types where possible.
It has been suggested that libraries information would include details about C++ version support. This might be in the form of badges for each of the various c++ versions. Note that criteria would need to be created to achieve a given badge.
The proposal is for a gradual deprecation of older compiler and standard support. The advanced version will continue to support older C++versions for at least 6 years and LTS for 9 years.
- 2019 LTS will move to C++11 and C++98 will be dropped, advanced to 14
- 2021 LTS will move to C++14 and 11 will be dropped, advanced to 17
- 2024 LTS will move to C++20 and 14 will be dropped, advanced to 20
The following timeline shows an example of the concept. Dates aren’t meant to be specific…
This would be done on a case by case basis, but dependent libraries will generally prefer std version libraries that overlap with standard. In particular, this would apply to libraries that are not changing and are part of community maintenance. Examples include boost.any and boost.array.
However, libraries that provide more advanced features than std, boost.thread or boost.smart_ptr for example, would continue in boost as an option for users. These libraries also have active maintainers and may lead to additional standards evolution.
The following is a more detailed outline of an approach for discussion:
- 2018 will become last full release with support for c++98/03
- first LTS release targeted for 2019 with minimum c++11 support
- subsequent LTS releases will continue with 1.xx release name
- 2019 first advanced release
- libraries to consider removing
- any – c++17 replacement, minimal recent change
- array – c++11 std:: replacement
- compatability – really old for broken obsolete compilers
- for_each – use range_for language feature
- function_types (replaced by CallableTraits, but lots of boost depend)
- min_max – std replacement in 11/14
- signals1 – long deprecated lib
- swap – std replacement
- assign, bind, call traits, enable_if, integer, lambda, lexical_cast, member function, move, result_of, value_initialized
- testing will only target c++14 and beyond
- advanced releases will be called boost2.x signalling a major revision
The proposal will have implications for external entities that ship boost. For example Linux distributions will need to decide which version of boost to include. However, by providing a regular release plan these parties will know what to expect from Boost evolution.
The proposal would require some additional management in GIT for libraries supported in both LTS and advanced.
There is also the potential to strain already limited release team resources. Beside the obvious recruitment of additional resources, we can keep the number of releases the same with 1 LTS release and as 2-3 advanced releases.
The proposal will should gradually reduce library interdependence as older libraries move toward depending more on std:: for things like shared_ptr.