carb/cpp/Memory.h

File members: carb/cpp/Memory.h

// Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//

#pragma once

#include "../Defines.h"

#include <memory>
#include <type_traits>

namespace carb
{
namespace cpp
{

#if !CARB_HAS_CPP17 || defined DOXYGEN_BUILD

template <typename T>
constexpr T* addressof(T& arg) noexcept
{
    return __builtin_addressof(arg);
}

template <typename T>
T const* addressof(T const&&) = delete;

#else

using std::addressof;

#endif

template <typename T>
constexpr std::enable_if_t<!std::is_array<T>::value> destroy_at(T* const p) noexcept(std::is_nothrow_destructible<T>::value)
{
    p->~T();
}

template <typename T, std::size_t N>
constexpr void destroy_at(T (*array)[N]) noexcept
{
    static_assert(noexcept(carb::cpp::destroy_at(array[0])),
                  "destroy_at for array requires elements to have noexcept destructor");

    for (T& elem : *array)
    {
        carb::cpp::destroy_at(carb::cpp::addressof(elem));
    }
}

#if !CARB_HAS_CPP20 || defined DOXYGEN_BUILD

template <typename T, typename... TArgs>
T* construct_at(T* place, TArgs&&... args) noexcept
    CARB_NO_DOC((noexcept(::new (static_cast<void*>(place)) T(std::forward<TArgs>(args)...))))
{
    return ::new (static_cast<void*>(place)) T(std::forward<TArgs>(args)...);
}

#else

using std::construct_at;

#endif

} // namespace cpp
} // namespace carb