I recently switched from the Microsoft compiler to GCC. Among many things, I noticed that std::make_unique became unavailable. This is apparently because make_unique is not part of C++11 standard, and Microsoft just happened to include it as an extension.
We are planning to move to C++14 soon, but in the mean while I wrote this "shim" function, and put it into std.
namespace std
{
template<typename T, typename... TArgs>
unique_ptr<T> make_unique(TArgs&&... args)
{
return std::unique_ptr<T>(new T(std::forward<TArgs>(args)...));
}
}
This solved that problem on gcc. However, I imagine it would cause problems back at Microsoft's side, since it would be a duplicate definition.
Is there a way to correctly shim functionality into std, so that it wouldn't cause trouble on different compilers / C++ standards? I looked around and didn't come up with anything. I thought maybe something like an include guard, for specific standard functions?
#ifndef MAKE_UNIQUE_DEFINED
#define MAKE_UNIQUE_DEFINED
// Define make_unique
#endif
Sadly it seems std doesn't define include guards for specific functions. Is there anything else I can do to make this more correct and compiler / c++ standard agnostic?
You can, actually. Just turn the two conditions you mentioned in your post to a conditional macro definition:
#if defined(_MSC_VER) && __cplusplus == 201103L
# define MAKE_UNIQUE_DEFINED 1
#endif
_MSC_VER checks the TU is compiled with MSVC. It's one of their predefined macros. You can use it to further refine the check, since it's the encoded version number of MSVC.__cplusplus when the TU is compiled as C++11 (this is standard, across platforms).__cplusplus isn't correctly defined for you (because Microsoft), you can use the _MSVC_LANG macro in its stead.The above can be used to wrap your "shim", as you originally planned. Or any other MSVC extension that pertains to these versions, as a matter of fact.
As an alternative, to avoid reopening the std namespace (a no-no). You could use namespacing to have the definition present in a safe place, and control how your program interprets it:
namespace extended_std {
#ifdef MAKE_UNIQUE_DEFINED
inline namespace
#else
namespace
#endif
shim {
// your definition goes here
}
#ifndef MAKE_UNIQUE_DEFINED
using std::make_unique;
#endif
}
The macro is then only there to control what extended_std::make_unique refers to. It either makes the namespace inline, pouring its content into the enclosing one. Or adds a using declaration for std::make_unique.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With