I have a project that currently uses C++11/14, but it requires something like std::filesystem
, which is only available in C++17, and hence I don't have a chance to currently use it. I see, however, that it's available in my current compiler as std::experimental::filesystem
. Is it a good idea to use experimental features, assuming that I could in the future add something like:
#ifdef CXX17 //if this is C++17
std::filesystem::something ...;
#else
std::experimental::filesystem::something ...;
#endif
My concerns are:
1. Is it guaranteed that all compliant compilers have the same experimental features?
2. Are experimental features prone to big changes that make them unreliable?
Maybe there's more things to wonder about. Why should I or should I not use them? I'm puzzled with a new project and don't know what to decide.
- Is it guaranteed that all compliant compilers have the same experimental features?
No, experimental features are optional.
- Are experimental features prone to big changes that make them unreliable?
Yes, the C++ committee might even decide to abandon a feature or in the process of standardization a defect might come up that would force a feature to change.
Generally, it's not a good idea to depend on experimental features. Experimental features are exactly what the word says (i.e., to experiment with).
Someone from the audience asked a question during the "C++ Standard Library Panel" talk at CppCon 2016 (YouTube) about the potential for the name experimental
to scare users away from using anything within the namespace:
Do you guys consider [the contents of the std::experimental
namespace] production ready and is that an argument that can be made, [that] it's effectively production ready for the next 3 years, and maybe you have to change your code 3 years later, maybe?
Michael Wong (chair of SG5 and SG14 and editor of the Concurrency TS) fielded the question first:
I think there's strong consensus within the committee that it is practically production ready. As I said before, in most cases 99% of it gets air-dropped in. We want to make sure that it's not an impediment for you to use it. You can understand why we want to put big features, large groups of features, in such a context, so that it doesn't disturb the rest of the whole library system, but it also makes it easier for you to use it. Now you can turn on GCC with a specific flag for Concepts, you know, that actually makes it easier for you to segment it out.
Alisdair Meredith (former chair of the LWG) then followed up:
I'm going to take the contrary position here. One of the things Herb [Sutter] said as convener of WG21, the standard group, when we set off down the path of TSes is, he didn't think that TSes will have succeeded until we have failed to bring something forward, because it means we're not being experimental enough, we're not being ambitious enough in what we're using the TSes for. We really do want that experimental
to be a hint that, yes, these things are subject to change, we're not binding to that, and we can get things wrong. This is to lower our barrier for the things we consider to be as ambitious and reach as we can [...] Now the standard seems to be on a three-year release cycle, we should be much more ambitious in putting really experimental features into the TS, and perhaps advancing things more rapidly into the main standard itself. But again, this will be a fun topic for us to discuss at the next few [C++ standard committee] meetings.
Stephan T. Lavavej (maintainer of Microsoft's STL implementation) was last to respond:
It's important to draw a distinction between the experimentalness of interface and the experimentalness of the implementation, because when you say "production ready", what does that mean? Usually, "production ready", you would think of that talking about the implementation. It's quite possible for an implementation [of something in std::experimental
] to be absolutely [...] bulletproof. [...] Something like [...] the <random>
header in TR1, [it was] really, really nice in TR1, and you could have had an absolutely bullet-proof implementation of that, but it turned out that the interface churned substantially [before the release of] C++11 and [...] if we knew back then what we do now, putting in an experimental
would have been a better signal to people that, "Hey, maybe you don't want to use std::experimental::variate_generator
because, ha-ha, it's going to disappear in C++11".
So it seems that there is some desire among the standard library developers and committee members that, in the future at least, the contents of the std::experimental
namespace should be truly "experimental" in nature, and it should not be taken for granted that something in std::experimental
will make it into the C++ standard.
And no, as far as I understand, it is up to standard library vendors as to whether they provide implementations for the various features within std::experimental
.
"Experimental" is a slightly exaggerated term. The filesystem
library originated in Boost and went through a few iterations there, before being submitted to ISO.
However, ISO standards are intentionally very conservative. Calling it experimental means ISO explicitly doesn't promise that the naming will be stable; it's abundantly clear that you will need to re-address your code some time in the future. But knowing ISO, it's likely that there will be guidance how.
As for compatibility between compilers, expect it to be reasonable. But there will be corner cases (think Windows drive-relative paths for instance), and that's exactly why a future standard might break your existing code. Ideally, it would break you code if and only if you depended on that corner case, but that's not a guarantee.
Maybe there's more things to wonder about.
A few points to consider:
How multiplatform is your project? If there is only one compiler involved, then you can inspect its implementation and track record to decide. Or ask them!
How large is your codebase? How large would be the impact of changes?
How fundamental to your project are the features provided by the API/library/feature?
What are the alternatives?
- Use experimental feature, then adapt code to modifications when/if it becomes standardized. Might be as easy as deleting
experimental::
, or as hard as forcing workarounds.
- Add an abstraction layer (Serge Ballesta comment). If the experimental feature changes your re-writes are isolated. For a standard feature, it might be overkill (std::filesystem is already an abstraction layer...).
- Use another API/library. Same questions: maturity? robustness? stability? portability? ease of use? features?
- In the case of std::filesystem (or the networking TS), there is boost::filesystem (resp. boost::asio) as an alternative or fallback, in case the
experimental
one fails or desappears.