// vi:set ft=cpp: -*- Mode: C++ -*-
/*
 * Copyright (C) 2016, 2019-2020, 2025 Kernkonzept GmbH.
 * Author(s): Philipp Eppelt <philipp.eppelt@kernkonzept.com>
 *
 * License: see LICENSE.spdx (in this directory or the directories above)
 */
#pragma once

#include <memory>
#include <utility>

namespace std { namespace L4 {

template <typename T>
struct _Make_unique
{ using __single = ::std::unique_ptr<T>; };

template <typename T>
struct _Make_unique<T[]>
{ using __array = ::std::unique_ptr<T[]>; };

template <typename T, size_t SIZE>
struct _Make_unique<T[SIZE]>
{ struct __invalid { }; };

/// Create an object of type `T` and return it inside a std::unique_ptr.
template <typename T, typename... Args>
inline typename _Make_unique<T>::__single
make_unique(Args &&... args)
{
  return ::std::unique_ptr<T>(new T(::std::forward<Args>(args)...));
}

/// Allocate an array of type `T` and return it inside a std::unique_ptr.
template <typename T>
inline typename _Make_unique<T>::__array
make_unique(std::size_t size)
{
  return ::std::unique_ptr<T>(new typename std::remove_extent<T>::type[size]());
}

/// Disable std::make_unqiue for arrays of known bound.
template <typename T, typename... Args>
inline typename _Make_unique<T>::__invalid
make_unique(Args &&...) = delete;
}} // namespace L4, namespace std
