Skip to content

Commit

Permalink
Add more meta functions
Browse files Browse the repository at this point in the history
  • Loading branch information
KredeGC committed Jun 23, 2023
1 parent 7a4a1ab commit 39c5e94
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 37 deletions.
32 changes: 18 additions & 14 deletions include/ktl/allocators/cascading.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ namespace ktl
cascading(const cascading&) = delete;

cascading(cascading&& other)
noexcept(noexcept(node(std::declval<node&&>()))) :
noexcept(std::is_nothrow_move_constructible_v<node>) :
m_Node(std::move(other.m_Node))
{
other.m_Node = nullptr;
Expand All @@ -62,7 +62,7 @@ namespace ktl
cascading& operator=(const cascading&) = delete;

cascading& operator=(cascading&& rhs)
noexcept(noexcept(m_Node = std::move(rhs.m_Node)))
noexcept(std::is_nothrow_move_assignable_v<node>)
{
release();

Expand Down Expand Up @@ -93,9 +93,9 @@ namespace ktl
* @return A location in memory that is at least @p n bytes big or nullptr if it could not be allocated
*/
void* allocate(size_type n) noexcept(
noexcept(detail::aligned_new<node>(detail::ALIGNMENT)) &&
noexcept(std::declval<Alloc&>().allocate(n)) &&
(!detail::has_max_size_v<Alloc> || noexcept(std::declval<Alloc&>().max_size())))
std::is_nothrow_default_constructible_v<node> &&
detail::has_nothrow_allocate_v<Alloc> &&
(!detail::has_max_size_v<Alloc> || detail::has_nothrow_max_size_v<Alloc>))
{
// Add an initial allocator
if (!m_Node)
Expand Down Expand Up @@ -132,8 +132,10 @@ namespace ktl
* @param p The location in memory to deallocate
* @param n The size that was initially allocated
*/
void deallocate(void* p, size_type n)
noexcept(noexcept(detail::aligned_delete(std::declval<node*>())) && noexcept(std::declval<Alloc&>().owns(p)) && noexcept(std::declval<Alloc&>().deallocate(p, n)))
void deallocate(void* p, size_type n) noexcept(
std::is_nothrow_destructible_v<node> &&
detail::has_nothrow_owns_v<Alloc> &&
detail::has_nothrow_deallocate_v<Alloc>)
{
KTL_ASSERT(p != nullptr);

Expand Down Expand Up @@ -173,8 +175,9 @@ namespace ktl
*/
template<typename T, typename... Args>
typename std::enable_if<detail::has_construct_v<Alloc, T*, Args...>, void>::type
construct(T* p, Args&&... args)
noexcept(noexcept(std::declval<Alloc&>().owns(p)) && detail::has_noexcept_construct_v<Alloc, T*, Args...>)
construct(T* p, Args&&... args) noexcept(
detail::has_nothrow_owns_v<Alloc> &&
detail::has_noexcept_construct_v<Alloc, T*, Args...>)
{
node* next = m_Node;
while (next)
Expand All @@ -201,8 +204,9 @@ namespace ktl
*/
template<typename T>
typename std::enable_if<detail::has_destroy_v<Alloc, T*>, void>::type
destroy(T* p)
noexcept(noexcept(std::declval<Alloc&>().owns(p)) && detail::has_noexcept_destroy_v<Alloc, T*>)
destroy(T* p) noexcept(
detail::has_nothrow_owns_v<Alloc> &&
detail::has_noexcept_destroy_v<Alloc, T*>)
{
node* next = m_Node;
while (next)
Expand Down Expand Up @@ -232,7 +236,7 @@ namespace ktl
template<typename A = Alloc>
typename std::enable_if<detail::has_max_size_v<A>, size_type>::type
max_size() const
noexcept(noexcept(std::declval<A&>().max_size()))
noexcept(detail::has_nothrow_max_size_v<A>)
{
return m_Node->Allocator.max_size();
}
Expand All @@ -243,7 +247,7 @@ namespace ktl
* @return Whether the allocator owns @p p
*/
bool owns(void* p) const
noexcept(noexcept(std::declval<Alloc&>().owns(p)))
noexcept(detail::has_nothrow_owns_v<Alloc>)
{
node* next = m_Node;
while (next)
Expand All @@ -260,7 +264,7 @@ namespace ktl

private:
void release()
noexcept(noexcept(detail::aligned_delete(m_Node)))
noexcept(std::is_nothrow_destructible_v<node>)
{
node* next = m_Node;
while (next)
Expand Down
21 changes: 9 additions & 12 deletions include/ktl/allocators/fallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ namespace ktl
public:
typedef typename detail::get_size_type_t<P> size_type;

fallback()
noexcept(std::is_nothrow_default_constructible_v<P> && std::is_nothrow_default_constructible_v<F>) :
m_Primary(),
m_Fallback() {}
fallback() = default;

/**
* @brief Constructor for forwarding a single argument to the primary allocator
Expand Down Expand Up @@ -101,7 +98,7 @@ namespace ktl

#pragma region Allocation
void* allocate(size_t n)
noexcept(noexcept(m_Primary.allocate(n)) && noexcept(m_Fallback.allocate(n)))
noexcept(detail::has_nothrow_allocate_v<P> && detail::has_nothrow_allocate_v<F>)
{
void* ptr = m_Primary.allocate(n);
if (!ptr)
Expand All @@ -110,7 +107,7 @@ namespace ktl
}

void deallocate(void* p, size_t n)
noexcept(noexcept(m_Primary.deallocate(p, n)) && noexcept(m_Fallback.deallocate(p, n)))
noexcept(detail::has_nothrow_deallocate_v<P>&& detail::has_nothrow_deallocate_v<F>)
{
if (m_Primary.owns(p))
{
Expand All @@ -126,8 +123,8 @@ namespace ktl
template<typename T, typename... Args>
typename std::enable_if<detail::has_construct_v<P, T*, Args...> || detail::has_construct_v<F, T*, Args...>, void>::type
construct(T* p, Args&&... args) noexcept(
(!detail::has_construct_v<P, T*, Args...> || detail::has_noexcept_construct_v<P, T*, Args...>) &&
(!detail::has_construct_v<F, T*, Args...> || detail::has_noexcept_construct_v<F, T*, Args...>) &&
(!detail::has_construct_v<P, T*, Args...> || detail::has_nothrow_construct_v<P, T*, Args...>) &&
(!detail::has_construct_v<F, T*, Args...> || detail::has_nothrow_construct_v<F, T*, Args...>) &&
std::is_nothrow_constructible_v<T, Args...>)
{
bool owned = m_Primary.owns(p);
Expand Down Expand Up @@ -156,8 +153,8 @@ namespace ktl
template<typename T>
typename std::enable_if<detail::has_destroy_v<P, T*> || detail::has_destroy_v<F, T*>, void>::type
destroy(T* p) noexcept(
(!detail::has_destroy_v<P, T*> || detail::has_noexcept_destroy_v<P, T*>) &&
(!detail::has_destroy_v<F, T*> || detail::has_noexcept_destroy_v<F, T*>) &&
(!detail::has_destroy_v<P, T*> || detail::has_nothrow_destroy_v<P, T*>) &&
(!detail::has_destroy_v<F, T*> || detail::has_nothrow_destroy_v<F, T*>) &&
std::is_nothrow_destructible_v<T>)
{
bool owned = m_Primary.owns(p);
Expand Down Expand Up @@ -188,15 +185,15 @@ namespace ktl
template<typename Primary = P, typename Fallback = F>
typename std::enable_if<detail::has_max_size_v<Primary> && detail::has_max_size_v<Fallback>, size_type>::type
max_size() const
noexcept(detail::has_nothrow_max_size_v<P> && detail::has_nothrow_max_size_v<F>)
noexcept(detail::has_nothrow_max_size_v<Primary> && detail::has_nothrow_max_size_v<Fallback>)
{
return (std::max)(m_Primary.max_size(), m_Fallback.max_size());
}

template<typename Primary = P, typename Fallback = F>
typename std::enable_if<detail::has_owns_v<Primary> && detail::has_owns_v<Fallback>, bool>::type
owns(void* p) const
noexcept(detail::has_nothrow_owns_v<P> && detail::has_nothrow_owns_v<F>)
noexcept(detail::has_nothrow_owns_v<Primary> && detail::has_nothrow_owns_v<Fallback>)
{
if (m_Primary.owns(p))
return true;
Expand Down
4 changes: 2 additions & 2 deletions include/ktl/allocators/overflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace ktl
* @param stream The stream to use when leaks or corruption happens
*/
explicit overflow(Stream& stream)
noexcept(noexcept(Alloc())) :
noexcept(std::is_nothrow_default_constructible_v<Alloc>) :
m_Stream(stream),
m_Alloc(),
m_Allocs(0),
Expand All @@ -46,7 +46,7 @@ namespace ktl
typename = std::enable_if_t<
detail::can_construct_v<Alloc, Args...>>>
explicit overflow(Stream& stream, Args&&... args)
noexcept(noexcept(Alloc(std::declval<Args>()...))) :
noexcept(std::is_nothrow_constructible_v<Alloc, Args...>) :
m_Stream(stream),
m_Alloc(std::forward<Args>(args)...),
m_Allocs(0),
Expand Down
15 changes: 6 additions & 9 deletions include/ktl/allocators/type_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ namespace ktl
* @brief Default constructor
* @note Only defined if the underlying allocator defines it
*/
template<typename = std::enable_if_t<std::is_default_constructible_v<Alloc>>>
type_allocator()
noexcept(std::is_nothrow_default_constructible_v<Alloc>) :
m_Alloc() {}
type_allocator() = default;

/**
* @brief Constructor for forwarding any arguments to the underlying allocator
Expand All @@ -52,7 +49,7 @@ namespace ktl
typename = std::enable_if_t<
detail::can_construct_v<Alloc, Args...>>>
explicit type_allocator(Args&&... alloc)
noexcept(noexcept(Alloc(std::declval<Args>()...))) :
noexcept(std::is_nothrow_constructible_v<T, Args...>) :
m_Alloc(std::forward<Args>(alloc)...) {}

type_allocator(const type_allocator&) = default;
Expand All @@ -61,12 +58,12 @@ namespace ktl

template<typename U>
type_allocator(const type_allocator<U, Alloc>& other)
noexcept(noexcept(Alloc(other.m_Alloc))) :
noexcept(std::is_nothrow_constructible_v<Alloc, const type_allocator<U, Alloc>&>) :
m_Alloc(other.m_Alloc) {}

template<typename U>
type_allocator(type_allocator<U, Alloc>&& other)
noexcept(noexcept(Alloc(std::move(other.m_Alloc)))) :
noexcept(std::is_nothrow_constructible_v<Alloc, type_allocator<U, Alloc>&&>) :
m_Alloc(std::move(other.m_Alloc)) {}

type_allocator& operator=(const type_allocator&) = default;
Expand Down Expand Up @@ -180,14 +177,14 @@ namespace ktl

template<typename T, typename U, typename Alloc>
bool operator==(const type_allocator<T, Alloc>& lhs, const type_allocator<U, Alloc>& rhs)
noexcept(noexcept(std::declval<type_allocator<T, Alloc>&>().get_allocator() == std::declval<type_allocator<U, Alloc>&>().get_allocator()))
noexcept(noexcept(lhs.get_allocator() == rhs.get_allocator()))
{
return lhs.get_allocator() == rhs.get_allocator();
}

template<typename T, typename U, typename Alloc>
bool operator!=(const type_allocator<T, Alloc>& lhs, const type_allocator<U, Alloc>& rhs)
noexcept(noexcept(std::declval<type_allocator<T, Alloc>&>().get_allocator() != std::declval<type_allocator<U, Alloc>&>().get_allocator()))
noexcept(noexcept(lhs.get_allocator() != rhs.get_allocator()))
{
return lhs.get_allocator() != rhs.get_allocator();
}
Expand Down
8 changes: 8 additions & 0 deletions include/ktl/utility/meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ namespace ktl::detail



// has allocate(size_t) noexcept
template<typename Alloc>
constexpr bool has_nothrow_allocate_v = noexcept(std::declval<Alloc&>().allocate(std::declval<size_t>()));

// has deallocate(void*, size_t) noexcept
template<typename Alloc>
constexpr bool has_nothrow_deallocate_v = noexcept(std::declval<Alloc&>().deallocate(std::declval<void*>(), std::declval<size_t>()));

// has construct(T*, Args&&...) noexcept
template<typename Void, typename... Types>
struct has_nothrow_construct : std::false_type {};
Expand Down

0 comments on commit 39c5e94

Please sign in to comment.