Program Listing for File placement.hpp
↰ Return to documentation for file (/tmp/ws/src/proxsuite/include/proxsuite/linalg/veg/memory/placement.hpp
)
#ifndef VEG_PLACEMENT_HPP_LP0HMLTPS
#define VEG_PLACEMENT_HPP_LP0HMLTPS
#include "proxsuite/linalg/veg/type_traits/constructible.hpp"
#include "proxsuite/linalg/veg/internal/std.hpp"
#include "proxsuite/linalg/veg/type_traits/invocable.hpp"
#include "proxsuite/linalg/veg/memory/address.hpp"
#include "proxsuite/linalg/veg/internal/prologue.hpp"
#include <new>
#if defined(VEG_WITH_CXX20_SUPPORT) && !VEG_HAS_BUILTIN(__builtin_bit_cast)
#include <bit>
#define VEG_HAS_BITCAST 1
#define VEG_BITCAST(T, x) ::std::bit_cast<T>(x)
#define VEG_BITCAST_CONSTEXPR constexpr
#elif VEG_HAS_BUILTIN(__builtin_bit_cast)
#define VEG_HAS_BITCAST 1
#define VEG_BITCAST(T, x) __builtin_bit_cast(T, x)
#define VEG_BITCAST_CONSTEXPR constexpr
#else
#include <cstring>
#define VEG_HAS_BITCAST 0
#define VEG_BITCAST_CONSTEXPR
#endif
// construct_at
#if defined(VEG_WITH_CXX20_SUPPORT)
// std::construct_at
#if __VEG_HAS_INCLUDE(<bits / stl_construct.h>) && \
__VEG_HAS_INCLUDE(<bits / stl_iterator_base_types.h>) && \
__VEG_HAS_INCLUDE(<bits / stl_iterator_base_funcs.h>)
#include <bits/stl_iterator_base_types.h>
#include <bits/stl_iterator_base_funcs.h>
#include <bits/stl_construct.h>
#else
#include <memory>
#endif
#endif
#if VEG_HAS_BUILTIN(__builtin_launder) || __GNUC__ >= 7
#define VEG_LAUNDER(p) (__builtin_launder(p))
#elif defined(VEG_WITH_CXX17_SUPPORT)
#include <new>
#define VEG_LAUNDER(p) (::std::launder(p))
#else
#define VEG_LAUNDER(p) (+p)
#endif
namespace proxsuite {
namespace linalg {
namespace veg {
namespace mem {
namespace nb {
struct launder
{
VEG_TEMPLATE(typename T,
requires(VEG_CONCEPT(complete<T>)),
VEG_INLINE constexpr auto
operator(),
(mem, T*))
const VEG_NOEXCEPT->T* { return VEG_LAUNDER(mem); }
};
#undef VEG_LAUNDER
struct construct_at
{
VEG_TEMPLATE((typename T, typename... Args),
requires(!VEG_CONCEPT(const_type<T>) &&
VEG_CONCEPT(inplace_constructible<T, Args...>)),
VEG_INLINE VEG_CPP20(constexpr) auto
operator(),
(mem, T*),
(... args, Args&&))
const VEG_NOEXCEPT_IF(VEG_CONCEPT(nothrow_inplace_constructible<T, Args...>))
->T*
{
#if defined(VEG_WITH_CXX20_SUPPORT)
return ::std::construct_at(mem, VEG_FWD(args)...);
#else
return ::new (mem) T(VEG_FWD(args)...);
#endif
}
};
struct construct_with
{
VEG_TEMPLATE((typename T, typename Fn),
requires(!VEG_CONCEPT(const_type<T>) &&
VEG_CONCEPT(fn_once<Fn, T>)),
VEG_INLINE VEG_CPP20(constexpr) auto
operator(),
(mem, T*),
(fn, Fn&&))
const VEG_NOEXCEPT_IF(VEG_CONCEPT(nothrow_fn_once<Fn, T>))->T*
{
#if defined(VEG_WITH_CXX20_SUPPORT)
struct Convertor
{
Fn&& fn;
VEG_INLINE constexpr operator T() const&& VEG_NOEXCEPT_IF(
VEG_CONCEPT(nothrow_fn_once<Fn, T>))
{
return VEG_FWD(fn)();
}
};
return ::std::construct_at(mem, Convertor{ VEG_FWD(fn) });
#else
return ::new (mem) T(VEG_FWD(fn)());
#endif
}
};
struct destroy_at
{
VEG_TEMPLATE((typename T),
requires(VEG_CONCEPT(complete<T>)),
VEG_INLINE VEG_CPP14(constexpr) void
operator(),
(mem, T*))
const VEG_NOEXCEPT_IF(VEG_CONCEPT(nothrow_destructible<T>)) { mem->~T(); }
};
struct align_next
{
auto operator()(usize alignment, void* ptr) const VEG_NOEXCEPT->void*
{
using byte_ptr = unsigned char*;
std::uintptr_t lo_mask = alignment - 1U;
std::uintptr_t hi_mask = ~lo_mask;
auto const intptr = reinterpret_cast<std::uintptr_t>(ptr);
auto* const byteptr = static_cast<byte_ptr>(ptr);
auto offset = ((intptr + alignment - 1U) & hi_mask) - intptr;
return byteptr + offset;
}
auto operator()(usize alignment,
void const* ptr) const VEG_NOEXCEPT->void const*
{
return this->operator()(alignment, const_cast<void*>(ptr));
}
};
struct align_prev
{
auto operator()(usize alignment, void* ptr) const VEG_NOEXCEPT->void*
{
using byte_ptr = unsigned char*;
std::uintptr_t lo_mask = alignment - 1U;
std::uintptr_t hi_mask = ~lo_mask;
auto const intptr = reinterpret_cast<std::uintptr_t>(ptr);
auto* const byteptr = static_cast<byte_ptr>(ptr);
auto offset = ((intptr)&hi_mask) - intptr;
return byteptr + offset;
}
auto operator()(usize alignment,
void const* ptr) const VEG_NOEXCEPT->void const*
{
return this->operator()(alignment, const_cast<void*>(ptr));
}
};
} // namespace nb
VEG_NIEBLOID(align_next);
VEG_NIEBLOID(align_prev);
VEG_NIEBLOID(launder);
VEG_NIEBLOID(construct_at);
VEG_NIEBLOID(construct_with);
VEG_NIEBLOID(destroy_at);
namespace nb {
template<typename To>
struct bit_cast
{
VEG_TEMPLATE(typename From,
requires((VEG_CONCEPT(trivially_copyable<From>) && //
VEG_CONCEPT(trivially_copyable<To>) && //
(sizeof(From) == sizeof(To)))),
VEG_INLINE VEG_BITCAST_CONSTEXPR auto
operator(),
(from, From const&))
const VEG_NOEXCEPT->To
{
#if VEG_HAS_BITCAST
return VEG_BITCAST(To, from);
#else
alignas(To) unsigned char buf[sizeof(To)];
To* ptr = reinterpret_cast<To*>(static_cast<unsigned char*>(buf));
::std::memcpy(ptr, nb::addressof{}(from), sizeof(To));
return To(static_cast<To&&>(*nb::launder{}(ptr)));
#endif
}
};
} // namespace nb
VEG_NIEBLOID_TEMPLATE(typename To, bit_cast, To);
} // namespace mem
} // namespace veg
} // namespace linalg
} // namespace proxsuite
#include "proxsuite/linalg/veg/internal/epilogue.hpp"
#endif /* end of include guard VEG_PLACEMENT_HPP_LP0HMLTPS */