Inject namespace experimental to std

拜拜、爱过 提交于 2019-12-09 02:53:14

问题


Is it bad or good parctice to inject namespace std::experimental into std like following?

namespace std
{
namespace experimental
{
}
using namespace experimental;    
}

#include <experimental/optional>

int main()
{
    std::optional< int > o;
    return 0;
}

Or even in more modern form:

#if __has_include(<optional>)
# include <optional>
#elif __has_include(<experimental/optional>)
# include <experimental/optional>
namespace std
{
using namespace experimental;    
}
#else
#error !
#endif

int main()
{
    std::optional< int > o;
    return 0;
}

The intention to introduce std::experimental "sub-namespace" is clear because std::experimental currently contains a plenty of new libraries. I think it is very likely all them will migrate into namespace std without any substantial changes and user code written currently can rely upon this (am I totally wrong?). Otherwise all this code should be refactored to change from std::experimental:: to std:: in the future. It is not big deal, but there may be reasons not to do so.

The question is about both production code and not-too-serious code.


回答1:


Sounds like a bad idea.

First off, this is undefined behaviour. Standards draft N4140 says:

[namespace.std]/1: The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. [...]

A using-directive is a kind of declaration, so UB is the order for the day.

Secondly, things in std::experimental are very much subject to change. You might find that when things are moved into std proper that your code still compiles, but doesn't act in quite the same way. This is just asking for trouble, especially in production code.




回答2:


At work I spend a lot of time fighting this kind of speculative complexity (I'm looking for a good phrase that characterises the behavior, this is the best I've come up with so far).

As I see it, you're introducing complexity and risk now into your code, in order to avoid refactoring in the future. That's bad enough, but in this particular case I would even go so far as to say that refactoring is a poor word choice -- it's not so much refactoring as simple text substitution.

Going through the code to remove std::experimental's (or change then to std:: or std::something_else ) is really just a text substitution. In the best case you're looking at a quick command in your editor or ide. In the worst case you're looking at spending a couple hours writing a regex -- maybe in your editor, maybe in PERL or Ruby...

Those std::experiment's indicate that you're using experimental functionality, and it's good to have an explicit statement in your code to that effect. If and when certain libraries enter the standard, a competent programmer can quickly and easily make the necessary text substitutions. If your text editing skills aren't up to the task, don't hack up the language -- improve your text editing skills. It's an opportunity.

More genarally, write the simplest, cleanest code that satisfies your needs now, and be ready to change it as soon as circumstances change. This will usually result in more flexible code that supports your real future needs better than your speculations now.




回答3:


What you're doing introduces undefined behaviour. In general terms, I'd say that introducing undefined behaviour falls more in the realm of bad practice than in the realm of good practice.

According to the 1998 C++ standard, Section 17.4.3.1, para 1.

It is undefined for a C++ program to add declarations or definitions to namespace std or namespaces within namespace std unless otherwise specified. A program may add template specializations for any standard library template to namespace std. Such a specialization (complete or partial) of a standard library template results in undefined behavior unless the declaration depends on a user defined name of external linkage and unless the specialization meets the standard library requirements for the original template.

I don't have more recent versions of the standard (on my current machine) but, from memory, all releases of the C++ standard have a similar clause.




回答4:


Many libraries in std::experimental can and will change in ways that will break user code before they migrate to std, and they may not even migrate into std. This is why they put them in std::experimental.

std::experimental is intended for a relatively free-for-all place where you can introduce new proposed library features for C++, and compilers can implement them, without it breaking existing code. The implementations are in flux and are not standard. Some of them may make it into C++1z, but some of them may not, and those that do make it in may be changed, and those that don't make it in might make it into C++2x with substantial changes.

Simply look at the history of, say, Ranges. Or the coroutine/resumable functions stuff microsoft is proposing. Or the reflection working group. Or concepts.

The goal of this iteration of C++ is, dare I say it, to be Agile, and to fail fast. Many independent proposals work their way through the pipeline, with a goal to minimize inter-dependencies. If a given proposal isn't ready for prime time at the time a C++ standard is, it doesn't make it in. If it is ready, and worthwhile, it is added in modularly.

This was (to my understanding) done explicitly to avoid the mess where some part of the process got "too big to fail" and things that where not ready where published into the standard, or the standard release was delayed for years because something was not ready.

On top of the above, messing around with std in that way makes your program ill-formed with no diagnostic required, as other answers have pointed out.



来源:https://stackoverflow.com/questions/34629249/inject-namespace-experimental-to-std

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!