Skip to content

Instantly share code, notes, and snippets.

@lichray
Last active December 15, 2015 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lichray/5219299 to your computer and use it in GitHub Desktop.
Save lichray/5219299 to your computer and use it in GitHub Desktop.
Modified from N3588, make_unique; a syntax enthusiast's work.
#include <type_traits>
#include <iostream>
#include <memory>
struct default_init_t {};
default_init_t default_init;
template <typename T, typename = void>
struct make_unique;
template <typename T>
struct make_unique<T, typename std::enable_if<
not std::is_array<T>::value>::type> : std::unique_ptr<T> {
template <typename... Args>
make_unique(Args&&... args) :
std::unique_ptr<T>(new T(std::forward<Args>(args)...)) {}
make_unique(default_init_t) :
std::unique_ptr<T>(new T) {}
operator std::unique_ptr<T>() && {
return this;
}
};
template <typename T>
struct make_unique<T, typename std::enable_if<
std::is_array<T>::value>::type> {
make_unique() : braced_(true) {}
make_unique(size_t n) : braced_(false), sz_(n) {}
make_unique(make_unique&&) = delete;
make_unique& operator=(make_unique&&) = delete;
template <typename... Args>
auto operator()(Args&&... args) && -> std::unique_ptr<T> {
typedef typename std::remove_extent<T>::type U;
return std::unique_ptr<T>(braced_ ?
new U[sizeof...(Args)]{ std::forward<Args>(args)... } :
new U[sz_]{ std::forward<Args>(args)... });
}
auto operator()(default_init_t) && -> std::unique_ptr<T> {
typedef typename std::remove_extent<T>::type U;
return std::unique_ptr<T>(new U[sz_]);
}
private:
bool braced_;
size_t sz_;
};
// STL's tests
using namespace std;
void print(const unique_ptr<int[]>& up) {
for (int i = 0; i < 5; ++i) {
cout << up[i] << " ";
}
cout << endl;
}
void f(unique_ptr<int>) {}
int main() {
cout << *make_unique<int>() << endl;
cout << *make_unique<int>(1729) << endl;
cout << "\"" << *make_unique<string>() << "\"" << endl;
cout << "\"" << *make_unique<string>("meow") << "\"" << endl;
cout << "\"" << *make_unique<string>(6, 'z') << "\"" << endl;
cout << *make_unique<int>(default_init) << endl;
cout << "\"" << *make_unique<string>(default_init) << "\"" << endl;
print(make_unique<int[]>{5}());
print(make_unique<int[]>{5}(default_init));
print(make_unique<int[]>{5}(100, 200, 300));
print(make_unique<int[]>{}(111, 222, 333, 444, 555));
f(make_unique<int>(3));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment