Conditionally declare make_unique only if not provided by STL, otherwise, declare using std::make_unique

124 Views Asked by At

I have the following code:

namespace notstd{
  // Only Declare this if std::make_unique exists
  using std::make_unique; 
  
  // Only Declare this if std::make_unique DOES NOT exist
  template<class T,class...Args> //
  std::unique_ptr<T> make_unique(Args&&...args){
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  }
}

I would like the using declaration only declared if std::make_unique is defined (std::make_unique did not exist until C++14), otherwise, I would like to define my local version. I believe that this can be accomplished with SFINAE in C++11, but I cannot get it to work. Any advice?

2

There are 2 best solutions below

9
paxdiablo On

I would not actually try to do this with SFINAE, especially since adding to the std namespace is undefined behaviour except for certain limited scenarios like template specialisation - your approach seems to be less specialisation and more creation from scratch :-)

Instead, you could just use the __cplusplus macro to conditionally compile code based on the supported level. This is set to 201103 for C++11 and 201402 for C++14, so should be easily usable.

2
Remy Lebeau On

SFINAE is not the right way to handle this. C++11 and later actually provide a way of telling you whether specific standard language/library features are implemented or not. In this case, you can use the predefined __cpp_lib_make_unique macro, which is defined when std::make_unique() is implemented, eg:

#include <memory>

namespace notstd{

  #if __cpp_lib_make_unique

  // Only Declare this if std::make_unique exists
  using std::make_unique; 

  #else  

  // Only Declare this if std::make_unique DOES NOT exist
  template<class T,class...Args> //
  std::unique_ptr<T> make_unique(Args&&...args){
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  }

  #endif
}

See Feature testing and Library feature-test macros on cppreference.com for more details.