Added Logo
This commit is contained in:
@@ -43,7 +43,8 @@ public:
|
||||
using alloc_t = Alloc;
|
||||
|
||||
dynarray() : _alloc(), _size(0) {}
|
||||
dynarray()
|
||||
dynarray(size_t size) : _alloc(size), _size(size) { }
|
||||
dynarray(const alloc_t& alloc) : _alloc(alloc), _size(0) {}
|
||||
|
||||
private:
|
||||
allocation<element_t, alloc_t> _alloc;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#ifndef FENNEC_LANG_INTRINSICS_H
|
||||
#define FENNEC_LANG_INTRINSICS_H
|
||||
|
||||
// Most major compilers support __has_builtin
|
||||
// Most major compilers support __has_builtin, notably GCC, MINGW, CLANG, and MSVC
|
||||
#if defined(__has_builtin)
|
||||
|
||||
|
||||
@@ -91,6 +91,14 @@
|
||||
# define FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT 0
|
||||
#endif
|
||||
|
||||
// Difficult and Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_constructible)
|
||||
# define FENNEC_BUILTIN_CAN_CONSTRUCT 1
|
||||
# define FENNEC_BUILTIN_CAN_CONSTRUCT(type, args...) __is_constructible(type, args)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_CAN_CONSTRUCT 0
|
||||
#endif
|
||||
|
||||
|
||||
// For compilers without or differently named builtins
|
||||
#else
|
||||
|
||||
@@ -204,8 +204,18 @@ template<typename T0, typename T1> struct can_convert
|
||||
/// \brief shorthand
|
||||
/// \param T0 First type
|
||||
/// \param T1 Second type
|
||||
template<typename T0, typename T1> using can_convert_v = typename can_convert<T0, T1>::type;
|
||||
template<typename T0, typename T1> using can_convert_v
|
||||
= typename can_convert<T0, T1>::type;
|
||||
|
||||
|
||||
// fennec::is_constructible ============================================================================================
|
||||
|
||||
|
||||
template<typename ClassT, typename...ArgsT> struct can_construct
|
||||
: bool_constant<FENNEC_BUILTIN_CAN_CONSTRUCT(ClassT, ArgsT...)> {};
|
||||
|
||||
template<typename ClassT, typename...ArgsT> constexpr bool_t can_construct_v
|
||||
= can_construct<ClassT, ArgsT...>{};
|
||||
|
||||
//
|
||||
|
||||
|
||||
@@ -106,6 +106,8 @@ public:
|
||||
|
||||
/// \brief Rebinds the allocator type to produce an element type of type `TypeT`
|
||||
template<typename TypeT> using rebind = typename __rebind<Alloc, TypeT>::type;
|
||||
|
||||
// TODO: allocator_traits static functions
|
||||
};
|
||||
|
||||
|
||||
@@ -180,19 +182,22 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, initializes internal data to `null` and the capacity to `0`
|
||||
constexpr allocation() noexcept : _data(nullptr), _capacity(0) {}
|
||||
constexpr allocation() noexcept
|
||||
: _data(nullptr), _capacity(0) {}
|
||||
|
||||
///
|
||||
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
|
||||
/// \param n The number of elements of type `T` to allocate for
|
||||
constexpr allocation(size_t n) noexcept : _data(_alloc.al), _capacity(n) {}
|
||||
constexpr allocation(size_t n) noexcept
|
||||
: _data(_alloc.al), _capacity(n) {}
|
||||
|
||||
///
|
||||
/// \brief Allocator Constructor
|
||||
/// \param alloc The allocation object to copy.
|
||||
///
|
||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
||||
constexpr allocation(const alloc_t& alloc) noexcept : _alloc(alloc), _data(nullptr), _capacity(0) {}
|
||||
constexpr allocation(const alloc_t& alloc) noexcept
|
||||
: _alloc(alloc), _data(nullptr), _capacity(0) {}
|
||||
|
||||
///
|
||||
/// \brief Sized Allocator Constructor
|
||||
@@ -200,7 +205,24 @@ public:
|
||||
/// \param alloc The allocation object to copy.
|
||||
///
|
||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
||||
constexpr allocation(size_t n, const alloc_t& alloc) noexcept : _alloc(alloc), _data(nullptr), _capacity(0) {}
|
||||
constexpr allocation(size_t n, const alloc_t& alloc) noexcept
|
||||
: _alloc(alloc), _data(nullptr), _capacity(0) {}
|
||||
|
||||
///
|
||||
/// \brief Copy Constructor, creates an allocation of equal size and performs a byte-wise copy
|
||||
/// \param alloc The allocation to copy
|
||||
constexpr allocation(const allocation& alloc) noexcept
|
||||
: _alloc(alloc._alloc), _data(_alloc.allocate(alloc._capacity)), _capacity(alloc._capacity)
|
||||
{ fennec::memcpy(_data, alloc._data, alloc._capacity * sizeof(T)); }
|
||||
|
||||
///
|
||||
/// \brief Move Constructor, moves the data in `alloc` to the new object and cleans `alloc` so that it
|
||||
/// can safely destruct
|
||||
/// \param alloc The allocation to move
|
||||
constexpr allocation(allocation&& alloc) noexcept
|
||||
: _alloc(alloc._alloc), _data(alloc._data), _capacity(alloc._capacity)
|
||||
{ alloc._data = nullptr; alloc._capacity = 0; }
|
||||
|
||||
|
||||
///
|
||||
/// \brief Default Destructor, releases the memory block if still present
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef FENNEC_MEMORY_H
|
||||
#define FENNEC_MEMORY_H
|
||||
|
||||
#include <fennec/lang/type_traits.h>
|
||||
#include <fennec/memory/detail/__memory.h>
|
||||
|
||||
namespace fennec
|
||||
@@ -152,22 +153,6 @@ constexpr void* memset(void* dst, int ch, size_t n)
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
template<typename TypeT>
|
||||
struct default_delete
|
||||
{
|
||||
constexpr default_delete() noexcept = default;
|
||||
|
||||
template<class U> default_delete(const default_delete<U>&) noexcept;
|
||||
template<class U> default_delete(const default_delete<U[]>&) noexcept;
|
||||
};
|
||||
|
||||
template<typename TypeT>
|
||||
struct default_delete<TypeT[]>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_MEMORY_H
|
||||
|
||||
@@ -19,19 +19,105 @@
|
||||
#ifndef FENNEC_LANG_POINTERS_H
|
||||
#define FENNEC_LANG_POINTERS_H
|
||||
|
||||
#include <fennec/lang/type_traits.h>
|
||||
|
||||
template<typename TypeT, class DeleteT = >
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
template<typename TypeT>
|
||||
struct default_delete
|
||||
{
|
||||
///
|
||||
/// \brief Default constructor
|
||||
constexpr default_delete() noexcept = default;
|
||||
|
||||
///
|
||||
/// \brief Conversion Constructor
|
||||
/// \tparam ConvT of other deleter
|
||||
template<class ConvT> requires requires { can_convert<ConvT*, TypeT*>{}.value == true; }
|
||||
constexpr default_delete(const default_delete<ConvT>&) noexcept {}
|
||||
|
||||
///
|
||||
/// \brief Function Call Operator, calls `delete` on `ptr`
|
||||
/// \param ptr Memory resource to delete
|
||||
constexpr void operator()(TypeT* ptr) const noexcept
|
||||
{
|
||||
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
||||
static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type");
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TypeT>
|
||||
struct default_delete<TypeT[]>
|
||||
{
|
||||
///
|
||||
/// \brief Default constructor
|
||||
constexpr default_delete() noexcept = default;
|
||||
|
||||
///
|
||||
/// \brief Conversion Constructor
|
||||
/// \tparam ConvT of other deleter
|
||||
template<class ConvT> requires requires { can_convert<ConvT(*)[], TypeT(*)[]>{}.value == true; }
|
||||
constexpr default_delete(const default_delete<ConvT(*)[]>&) noexcept {}
|
||||
|
||||
///
|
||||
/// \brief Function Call Operator, calls `delete` on `ptr`
|
||||
/// \param ptr Memory resource to delete
|
||||
template<class ArrT> requires requires { can_convert<ArrT(*)[], TypeT(*)[]>{}.value == true; }
|
||||
constexpr void operator()(TypeT* ptr) const noexcept
|
||||
{
|
||||
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
||||
static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type");
|
||||
delete[] ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TypeT, class DeleteT = default_delete<TypeT>>
|
||||
class unique_ptr
|
||||
{
|
||||
public:
|
||||
/// \brief the element type
|
||||
using element_t = TypeT;
|
||||
|
||||
/// \brief pointer to element type
|
||||
using pointer_t = element_t*;
|
||||
|
||||
/// \brief the deleter
|
||||
using delete_t = DeleteT;
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, creates a unique_ptr that owns nothing.
|
||||
constexpr unique_ptr() : unique_ptr(nullptr) {}
|
||||
constexpr unique_ptr(pointer_t ptr) : _handle(ptr) {}
|
||||
|
||||
///
|
||||
/// \brief Nullptr Constructor, creates a unique_ptr that owns nothing.
|
||||
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr(nullptr) {}
|
||||
|
||||
///
|
||||
/// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del`
|
||||
/// \param ptr The resource to own
|
||||
/// \param del The deleter
|
||||
explicit constexpr unique_ptr(pointer_t ptr, const delete_t& del) : _delete(del), _handle(ptr) {}
|
||||
|
||||
///
|
||||
/// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del`
|
||||
/// \param ptr The resource to own
|
||||
/// \param del The deleter
|
||||
explicit constexpr unique_ptr(pointer_t ptr, delete_t&& del) : _delete(del), _handle(ptr) {}
|
||||
|
||||
///
|
||||
/// \brief Move Constructor, transfers ownership from `other`
|
||||
/// \param other The unique_ptr to take ownership from
|
||||
constexpr unique_ptr(unique_ptr&& other) : _handle(other._handle) { other._handle = nullptr; }
|
||||
|
||||
constexpr ~unique_ptr() { if(_handle) ::operator delete(_handle); }
|
||||
// Delete copy constructor
|
||||
constexpr unique_ptr(const unique_ptr&) = delete;
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, if it owns a resource, it deletes it using `delete_t`
|
||||
constexpr ~unique_ptr() { if(_handle) _delete(_handle); }
|
||||
|
||||
|
||||
constexpr unique_ptr& operator=(unique_ptr&& r) noexcept
|
||||
{ _handle = r._handle; r._handle = nullptr; return *this; }
|
||||
@@ -40,7 +126,10 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
delete_t _delete;
|
||||
pointer_t _handle;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_POINTERS_H
|
||||
|
||||
Reference in New Issue
Block a user