现代 C + + 的实验特性对于长期项目来说是否可靠?

我有一个目前使用 C + + 11/14的项目,但它需要类似于 std::filesystem的东西,这只在 C + + 17中可用,因此我目前没有机会使用它。但是,我发现它在我当前的编译器中可以作为 std::experimental::filesystem使用。使用实验性的功能是个好主意吗,假设我将来可以添加这样的东西:

#ifdef CXX17 //if this is C++17
std::filesystem::something ...;
#else
std::experimental::filesystem::something ...;
#endif

我担心的是:

1. 是否保证所有兼容的编译器都具有相同的实验特性?

2. 实验特性是否容易发生大的变化,使其不可靠?

也许还有更多值得怀疑的事。为什么我应该或不应该使用它们?我对一个新项目感到困惑,不知道该做什么决定。

12991 次浏览

"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.

  1. Is it guaranteed that all compliant compilers have the same experimental features?

No, experimental features are optional.

  1. 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.

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.