7

I came across a codebase that is fixed on C++11 features but implements std::make_unique. That is been done extending namespace std to add the feature if C++14 is not use, i.e. wrapping the implementation around

#if defined(__cplusplus) && __cplusplus < 201402L

namespace std {
  ...
}

#endif

I know that is undefined behavior to extend namespace std (with some exception). Is the case above still acceptable or should it be avoided in any case?

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
BeppeNanoso
  • 105
  • 4
  • You are in essence providing your own C++ implementation (based on an existing implementation of course), so *you* decide what's acceptable with this new implementation. – n. m. could be an AI Jul 26 '19 at 17:14
  • What you can do instead is a `using std::make_unique` in C++14 and define your own in C++11 and before. :) – Rakete1111 Jul 26 '19 at 17:17
  • Not necessarily a dupe, but very relevant: https://stackoverflow.com/questions/41062294/c-when-is-it-ok-to-extend-the-std-namespace –  Jul 26 '19 at 17:26

5 Answers5

8

No, this is forbidden—even though, via

#define make_unique ? ? ?

a conforming C++11 program can be quite sure that the library never mentions the name (outside of a stringization) and would thus be unable to detect the extension.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
  • 1
    Is it conforming to call functions in `std` via ADL? If so, `std::make_unique` can be detected: https://godbolt.org/z/Zhjnfq – Justin Jul 26 '19 at 18:08
  • @Justin: Certainly ADL can be used to call such functions. I’m not sure immediately whether that mechanism is itself conforming; I’ll edit if/when I figure that out. – Davis Herring Jul 26 '19 at 18:16
  • This is perhaps more likely to be conforming: https://godbolt.org/z/x-0KLf – Justin Jul 26 '19 at 18:35
  • @Justin: There is a [footnote](http://eel.is/c++draft/conforming#footnote-181) on this subject which sounds relevant but is really about overloads. Now that I think about it, `#define make_unique` is valid in C++11, so it would be difficult for a library to supply it after all. It would have trouble even detecting its own `make_unique` since it’s not allowed to assume the name isn’t a macro. It’s still true that it’s disallowed, but this explanation is more than a little lacking, sorry. – Davis Herring Jul 26 '19 at 18:49
5

The approach I've taken in this case is slightly different:

#if __cplusplus < 201402L

namespace std14 {
  ...
}

#else
     using namespace std14 = std;
#endif

Then you write your code like:

auto foo = std14::make_unique<T>(whatever);

...and for now it'll use your implementation of make_unique, but when/if you start using a C++14 compiler, it'll use the implementation provided by the compiler.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 1
    You technically shouldn't use `std14`, though. See [\[namespace.future\]](http://eel.is/c++draft/namespace.constraints#namespace.future): "Top level namespaces with a name starting with std and followed by a non-empty sequence of digits are reserved for future standardization." It's very unlikely that `std2` and the like will ever happen, though. – Justin Jul 26 '19 at 18:24
0

Is the case above still acceptable or should it be avoided in any case?

Whether relying on UB is acceptable or not depends on your environment, your users, your policies, etc.

In practical terms, whatever UB means depends on your implementation.

Acorn
  • 24,970
  • 5
  • 40
  • 69
  • I think the heart of what the OP is asking is that in some cases, [it's okay to extend std](https://stackoverflow.com/a/41062439/10957435), specifically template specialization. This question asks if their case is covered in the non UB portion. –  Jul 26 '19 at 17:23
  • That said, the remarks of Acorn are valid. I've already seen production code that calls internals of the STL directly. As long as your compiler can't (ab)use the UB and you are comfortable using it, it can 'work' (and backfire after some time) – JVApen Jul 26 '19 at 18:23
0

The only time it is okay to extend namespace std is template specialization:

The only case where it is OK to add a definition into the std namespace is specialization of a template that already exists in the namespace and to explicitly instantiate a template. However, only if they depend on a user defined type.

0

As it is undefined to put yourself that definition in namespace std

I would use:

#if __cplusplus < 201402L
namespace extended_std /* or more appropriate name */
{
    namespace std
    {
        // make_unique
    }
}

using namespace extended_std; // So you can use std::make_unique
                              // but not ::std::make_unique nor ADL usage :( .
#endif
Jarod42
  • 203,559
  • 14
  • 181
  • 302