- fennec::variant & fennec::generic, TODO: Test
This commit is contained in:
@@ -113,6 +113,7 @@ add_library(fennec STATIC
|
|||||||
include/fennec/containers/bitfield.h
|
include/fennec/containers/bitfield.h
|
||||||
include/fennec/containers/deque.h
|
include/fennec/containers/deque.h
|
||||||
include/fennec/containers/dynarray.h
|
include/fennec/containers/dynarray.h
|
||||||
|
include/fennec/containers/generic.h
|
||||||
include/fennec/containers/graph.h
|
include/fennec/containers/graph.h
|
||||||
include/fennec/containers/initializer_list.h
|
include/fennec/containers/initializer_list.h
|
||||||
include/fennec/containers/list.h
|
include/fennec/containers/list.h
|
||||||
@@ -176,6 +177,8 @@ add_library(fennec STATIC
|
|||||||
include/fennec/rtti/enable.h
|
include/fennec/rtti/enable.h
|
||||||
include/fennec/rtti/forward.h
|
include/fennec/rtti/forward.h
|
||||||
include/fennec/rtti/typelist.h
|
include/fennec/rtti/typelist.h
|
||||||
|
include/fennec/rtti/type_registry.h
|
||||||
|
include/fennec/rtti/singleton.h
|
||||||
|
|
||||||
|
|
||||||
include/fennec/rtti/detail/_constants.h
|
include/fennec/rtti/detail/_constants.h
|
||||||
|
|||||||
@@ -27,5 +27,4 @@ fennec_add_definitions(
|
|||||||
FENNEC_COMPILER_GCC=1
|
FENNEC_COMPILER_GCC=1
|
||||||
FENNEC_NO_INLINE=[[gnu::noinline]]
|
FENNEC_NO_INLINE=[[gnu::noinline]]
|
||||||
FENNEC_FUNCTION_NAME=__PRETTY_FUNCTION__
|
FENNEC_FUNCTION_NAME=__PRETTY_FUNCTION__
|
||||||
RYU_ONLY_64_BIT_OPS
|
|
||||||
)
|
)
|
||||||
|
|||||||
210
include/fennec/containers/generic.h
Normal file
210
include/fennec/containers/generic.h
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file universal.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_CONTAINERS_GENERIC_H
|
||||||
|
#define FENNEC_CONTAINERS_GENERIC_H
|
||||||
|
|
||||||
|
#include <fennec/memory/allocator.h>
|
||||||
|
#include <fennec/rtti/type.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief A struct capable of holding a single object of any type
|
||||||
|
struct generic {
|
||||||
|
|
||||||
|
// Definitions =========================================================================================================
|
||||||
|
private:
|
||||||
|
|
||||||
|
// based on GCC
|
||||||
|
enum op_ : uint8_t {
|
||||||
|
op_clone,
|
||||||
|
op_destroy,
|
||||||
|
op_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
using manager_t = void* (*)(uint8_t, void*);
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors ========================================================================================================
|
||||||
|
public:
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Constructor
|
||||||
|
generic()
|
||||||
|
: _handle(nullptr)
|
||||||
|
, _manage(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Constructor
|
||||||
|
/// \param gen The generic object to copy
|
||||||
|
generic(const generic& gen)
|
||||||
|
: _handle(nullptr)
|
||||||
|
, _manage(gen._manage) {
|
||||||
|
if (_manage) {
|
||||||
|
_handle = _manage(op_clone, gen._handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Constructor
|
||||||
|
/// \param gen The generic object to move
|
||||||
|
generic(generic&& gen)
|
||||||
|
: _handle(gen._handle)
|
||||||
|
, _manage(gen._manage) {
|
||||||
|
gen._handle = nullptr;
|
||||||
|
gen._manage = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Value Constructor
|
||||||
|
/// \tparam T The type of the value
|
||||||
|
/// \param x The value
|
||||||
|
template<typename T>
|
||||||
|
generic(T&& x)
|
||||||
|
: _handle(new T(fennec::forward<T>(x)))
|
||||||
|
, _manage(_manage_impl<T>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Constructor
|
||||||
|
/// \tparam T The type to construct
|
||||||
|
/// \tparam ArgsT The argument types
|
||||||
|
/// \param args The argument values
|
||||||
|
template<typename T, typename...ArgsT>
|
||||||
|
generic(type_identity<T>, ArgsT&&...args)
|
||||||
|
: _handle(new T(fennec::forward<ArgsT>(args)...))
|
||||||
|
, _manage(_manage_impl<T>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Destructor
|
||||||
|
~generic() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
|
type type() const {
|
||||||
|
return *static_cast<fennec::type*>(_manage(op_type, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_value() const {
|
||||||
|
return _handle != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
generic& operator=(const generic& gen) {
|
||||||
|
if (this == &gen) { // self-assignment case
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
|
_manage = gen._manage;
|
||||||
|
_handle = _manage(op_clone, gen._handle);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
generic& operator=(generic&& gen) noexcept {
|
||||||
|
swap(gen);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Utility =============================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
generic& operator=(T&& x) {
|
||||||
|
reset();
|
||||||
|
_handle = new T(fennec::forward<T>(x));
|
||||||
|
_manage = _manage_impl<T>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename...ArgsT>
|
||||||
|
void emplace(ArgsT&&...args) {
|
||||||
|
reset();
|
||||||
|
_handle = new T(fennec::forward<ArgsT>(args)...);
|
||||||
|
_manage = _manage_impl<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
if (_manage) {
|
||||||
|
_handle = _manage(op_destroy, _handle);
|
||||||
|
_manage = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(generic& gen) noexcept {
|
||||||
|
fennec::swap(_handle, gen._handle);
|
||||||
|
fennec::swap(_manage, gen._manage);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& cast() {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T& cast() const {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* _handle;
|
||||||
|
manager_t _manage;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static void* _manage_impl(uint8_t op, void* hnd) {
|
||||||
|
static fennec::type t = type::get<T>();
|
||||||
|
T* ptr = hnd;
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case op_clone:
|
||||||
|
return new T(*ptr);
|
||||||
|
case op_destroy:
|
||||||
|
delete ptr;
|
||||||
|
return nullptr;
|
||||||
|
case op_type:
|
||||||
|
return &t;
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_CONTAINERS_GENERIC_H
|
||||||
@@ -31,4 +31,216 @@
|
|||||||
#ifndef FENNEC_CONTAINERS_VARIANT_H
|
#ifndef FENNEC_CONTAINERS_VARIANT_H
|
||||||
#define FENNEC_CONTAINERS_VARIANT_H
|
#define FENNEC_CONTAINERS_VARIANT_H
|
||||||
|
|
||||||
|
#include <fennec/containers/optional.h>
|
||||||
|
#include <fennec/lang/type_sequences.h>
|
||||||
|
#include <fennec/math/ext/common.h>
|
||||||
|
#include <fennec/rtti/type.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief A structure that represents a union between `TypesT...`
|
||||||
|
/// \tparam TypesT The types to hold in the variant
|
||||||
|
template<typename...TypesT>
|
||||||
|
struct variant {
|
||||||
|
// Assertions ==========================================================================================================
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
is_unique_v<TypesT...> and // No two types in TypesT... may be equivalent
|
||||||
|
not (is_reference_v<TypesT> or ...) and // No type in TypesT... may be a reference
|
||||||
|
not (is_array_v<TypesT> or ...) and // No type in TypesT... may be an array
|
||||||
|
not (is_void_v<TypesT> or ...) // No type in TypesT... may be void
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Typedefs & Constants ================================================================================================
|
||||||
|
|
||||||
|
static constexpr size_t size = max_element_size_v<TypesT...>;
|
||||||
|
static constexpr size_t nulltype = sizeof...(TypesT);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors ========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Constructor, constructs the first type in `TypesT...` that is default constructible
|
||||||
|
variant()
|
||||||
|
: _bytes {}
|
||||||
|
, _type(nulltype) {
|
||||||
|
using construct_t = search_element_t<is_default_constructible, TypesT...>;
|
||||||
|
fennec::construct<construct_t>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Conversion Constructor, constructs the type in `TypesT...` that is identical to `T`
|
||||||
|
/// or the first that is constructible with `T`
|
||||||
|
/// \tparam T The type of the value
|
||||||
|
/// \param t The value to forward
|
||||||
|
template<typename T>
|
||||||
|
variant(T&& t)
|
||||||
|
: _bytes {}
|
||||||
|
, _type() {
|
||||||
|
using same_t = search_element_args<is_same, type_sequence<T>, TypesT...>;
|
||||||
|
using convert_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>;
|
||||||
|
using construct_t = conditional_t<is_void_v<same_t>, convert_t, convert_t>;
|
||||||
|
fennec::construct<construct_t>(_handle, fennec::forward<T>(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Emplace Constructor, constructs the first type in `TypesT...` that is constructible with `ArgsT...`
|
||||||
|
/// \tparam ArgsT The arguments of the constructor
|
||||||
|
/// \param args The argument values
|
||||||
|
template<typename T, typename...ArgsT>
|
||||||
|
variant(type_identity<T>, ArgsT&&...args)
|
||||||
|
: _bytes{}
|
||||||
|
, _type(nulltype) {
|
||||||
|
static_assert(contains_element_v<T, TypesT...>, "T must be in TypesT...");
|
||||||
|
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...);
|
||||||
|
_type = find_element_v<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Constructor
|
||||||
|
/// \param v The variant to copy
|
||||||
|
variant(const variant& v)
|
||||||
|
: _bytes {}
|
||||||
|
, _type(nulltype) {
|
||||||
|
|
||||||
|
if (v._type == nulltype) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
((v._type == find_element_v<TypesT, TypesT...> ?
|
||||||
|
fennec::construct<TypesT>(_handle, v.get<TypesT>()) :
|
||||||
|
(0)
|
||||||
|
), ...);
|
||||||
|
_type = v._type;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Constructor
|
||||||
|
/// \param v The variant to move
|
||||||
|
variant(variant&& v) noexcept
|
||||||
|
: _bytes {}
|
||||||
|
, _type() {
|
||||||
|
|
||||||
|
if (v._type == nulltype) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
((v._type == find_element_v<TypesT, TypesT...> ?
|
||||||
|
fennec::construct<TypesT>(_handle, fennec::move(v.get<TypesT>())) :
|
||||||
|
(0)
|
||||||
|
), ...);
|
||||||
|
_type = v._type;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Destructor, if a type is held, destruct it.
|
||||||
|
~variant() {
|
||||||
|
_clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
variant& operator=(T&& t) {
|
||||||
|
|
||||||
|
// First, check if `T` is in `TypesT...`
|
||||||
|
if constexpr((contains_element_v<T, TypesT> or ...)) {
|
||||||
|
using type_t = remove_reference_t<T>;
|
||||||
|
if (_type == find_element_v<type_t, TypesT...>) {
|
||||||
|
*static_cast<type_t*>(_handle) = fennec::forward<T>(t);
|
||||||
|
} else {
|
||||||
|
_clear();
|
||||||
|
fennec::construct<type_t>(_handle, fennec::forward<T>(t));
|
||||||
|
_type = find_element_v<type_t, TypesT...>;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, try to assign using the currently held type
|
||||||
|
bool assigned = false;
|
||||||
|
if (_type != nulltype) {
|
||||||
|
((_type == find_element_v<TypesT, TypesT...> ?
|
||||||
|
(*static_cast<TypesT*>(_handle) = fennec::forward<T>(t), assigned = true) :
|
||||||
|
(0)
|
||||||
|
), ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assigned) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, destruct, then construct
|
||||||
|
_clear();
|
||||||
|
using construct_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>;
|
||||||
|
fennec::construct<construct_t>(_handle, fennec::forward<T>(t));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename...ArgsT> requires(contains_element_v<T, TypesT...>)
|
||||||
|
void emplace(ArgsT&&...args) {
|
||||||
|
_clear();
|
||||||
|
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t I, typename...ArgsT>
|
||||||
|
void emplace(ArgsT&&...args) {
|
||||||
|
using type_t = nth_element_t<I, TypesT...>;
|
||||||
|
_clear();
|
||||||
|
fennec::construct<type_t>(fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Access ==============================================================================================================
|
||||||
|
|
||||||
|
template<typename T> requires(contains_element_v<T, TypesT...>)
|
||||||
|
T& get() {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> requires(contains_element_v<T, TypesT...>)
|
||||||
|
const T& get() const {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
||||||
|
T& get() {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
||||||
|
const T& get() const {
|
||||||
|
return *static_cast<T*>(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
union {
|
||||||
|
byte_t _bytes[size];
|
||||||
|
void* _handle;
|
||||||
|
};
|
||||||
|
size_t _type;
|
||||||
|
|
||||||
|
void _clear() {
|
||||||
|
if (_type == nulltype) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
((_type == find_element_v<TypesT, TypesT...> ?
|
||||||
|
fennec::destruct<TypesT>(_handle) :
|
||||||
|
(0)
|
||||||
|
), ...);
|
||||||
|
_type = nulltype;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif // FENNEC_CONTAINERS_VARIANT_H
|
#endif // FENNEC_CONTAINERS_VARIANT_H
|
||||||
@@ -19,13 +19,19 @@
|
|||||||
#ifndef FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
#ifndef FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
||||||
#define FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
#define FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
||||||
|
|
||||||
|
#include <fennec/math/common.h>
|
||||||
#include <fennec/lang/type_transforms.h>
|
#include <fennec/lang/type_transforms.h>
|
||||||
|
|
||||||
namespace fennec::detail
|
namespace fennec::detail
|
||||||
{
|
{
|
||||||
|
template<typename...TypesT> struct _type_sequence {};
|
||||||
|
|
||||||
template<typename FirstT, typename... RestT> struct _first_element : type_identity<FirstT> {};
|
template<typename FirstT, typename... RestT> struct _first_element : type_identity<FirstT> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::nth_element =================================================================================================
|
||||||
|
|
||||||
template<size_t n, size_t i, typename...TypesT> struct _nth_element;
|
template<size_t n, size_t i, typename...TypesT> struct _nth_element;
|
||||||
|
|
||||||
template<size_t n, size_t i> struct _nth_element<n, i> : type_identity<void> {};
|
template<size_t n, size_t i> struct _nth_element<n, i> : type_identity<void> {};
|
||||||
@@ -35,6 +41,56 @@ namespace fennec::detail
|
|||||||
n == i, HeadT,
|
n == i, HeadT,
|
||||||
typename _nth_element<n, i + 1, RestT...>::type
|
typename _nth_element<n, i + 1, RestT...>::type
|
||||||
> {};
|
> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::max_element_size ============================================================================================
|
||||||
|
|
||||||
|
template<size_t, typename...> struct _max_element_size;
|
||||||
|
|
||||||
|
template<size_t M, typename HeadT>
|
||||||
|
struct _max_element_size<M, HeadT>
|
||||||
|
: integral_constant<size_t, fennec::max(M, sizeof(HeadT))> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t M, typename HeadT, typename...RestT>
|
||||||
|
struct _max_element_size<M, HeadT, RestT...>
|
||||||
|
: _max_element_size<fennec::max(M, sizeof(HeadT)), RestT...> {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::find_element ================================================================================================
|
||||||
|
|
||||||
|
template<size_t N, typename, typename...> struct _find_element;
|
||||||
|
|
||||||
|
template<size_t N, typename FindT, typename HeadT>
|
||||||
|
struct _find_element<N, FindT, HeadT> : integral_constant<size_t, is_same_v<FindT, HeadT> ? N : N + 1> {};
|
||||||
|
|
||||||
|
template<size_t N, typename FindT, typename HeadT, typename...RestT> requires(is_same_v<FindT, HeadT>)
|
||||||
|
struct _find_element<N, FindT, HeadT, RestT...>
|
||||||
|
: conditional_t<is_same_v<FindT, HeadT>, integral_constant<size_t, N>, _find_element<N + 1, FindT, RestT...>> {};
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::search_element ==============================================================================================
|
||||||
|
|
||||||
|
template<template<typename> typename, typename...> struct _search_element;
|
||||||
|
|
||||||
|
template<template<typename> typename SearchT> struct _search_element<SearchT> : type_identity<void> {};
|
||||||
|
|
||||||
|
template<template<typename> typename SearchT, typename HeadT, typename...RestT> requires(SearchT<HeadT>{})
|
||||||
|
struct _search_element<SearchT, HeadT, RestT...>
|
||||||
|
: conditional_t<SearchT<HeadT>{}, type_identity<HeadT>, _search_element<SearchT, RestT...>> {
|
||||||
|
};
|
||||||
|
|
||||||
|
template<template<typename, typename...> typename, typename, typename...> struct _search_element_args;
|
||||||
|
|
||||||
|
template<template<typename, typename...> typename SearchT, typename...ArgsT>
|
||||||
|
struct _search_element_args<SearchT, _type_sequence<ArgsT...>> : type_identity<void> {};
|
||||||
|
|
||||||
|
template<template<typename, typename...> typename SearchT, typename HeadT, typename...RestT, typename...ArgsT>
|
||||||
|
struct _search_element_args<SearchT, _type_sequence<ArgsT...>, HeadT, RestT...>
|
||||||
|
: conditional_t<SearchT<HeadT, ArgsT...>{}, type_identity<HeadT>, _search_element_args<SearchT, _type_sequence<ArgsT...>, RestT...>> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
#endif // FENNEC_LANG_DETAIL_TYPE_SEQUENCES_H
|
||||||
|
|||||||
@@ -63,9 +63,19 @@ namespace fennec::detail
|
|||||||
template<> struct _is_floating_point<float_t> : true_type {};
|
template<> struct _is_floating_point<float_t> : true_type {};
|
||||||
template<> struct _is_floating_point<double_t> : true_type {};
|
template<> struct _is_floating_point<double_t> : true_type {};
|
||||||
|
|
||||||
template<typename> struct _is_pointer : false_type {};
|
template<typename> struct _is_pointer : false_type {};
|
||||||
template<typename T> struct _is_pointer<T*> : true_type {};
|
template<typename T> struct _is_pointer<T*> : true_type {};
|
||||||
|
|
||||||
|
template<typename> struct _is_reference : false_type {};
|
||||||
|
template<typename T> struct _is_reference<T&> : true_type {};
|
||||||
|
template<typename T> struct _is_reference<T&&> : true_type {};
|
||||||
|
|
||||||
|
template<typename> struct _is_lvalue_reference : false_type {};
|
||||||
|
template<typename T> struct _is_lvalue_reference<T&> : true_type {};
|
||||||
|
|
||||||
|
template<typename> struct _is_rvalue_reference : false_type {};
|
||||||
|
template<typename T> struct _is_rvalue_reference<T&&> : true_type {};
|
||||||
|
|
||||||
template<typename T> struct _is_complete {
|
template<typename T> struct _is_complete {
|
||||||
template<typename U>
|
template<typename U>
|
||||||
static auto test(U*) -> bool_constant<sizeof(U) == sizeof(U)>;
|
static auto test(U*) -> bool_constant<sizeof(U) == sizeof(U)>;
|
||||||
|
|||||||
@@ -213,6 +213,14 @@
|
|||||||
# define FENNEC_HAS_BUILTIN_IS_ENUM 0
|
# define FENNEC_HAS_BUILTIN_IS_ENUM 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Inconsistent without intrinsics.
|
||||||
|
#if __has_builtin(__is_union)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_UNION 1
|
||||||
|
# define FENNEC_BUILTIN_IS_UNION(arg) __is_union(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_UNION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
// Inconsistent without intrinsics
|
// Inconsistent without intrinsics
|
||||||
#if __has_builtin(__is_final)
|
#if __has_builtin(__is_final)
|
||||||
# define FENNEC_HAS_BUILTIN_IS_FINAL 1
|
# define FENNEC_HAS_BUILTIN_IS_FINAL 1
|
||||||
@@ -221,12 +229,20 @@
|
|||||||
# define FENNEC_HAS_BUILTIN_IS_FINAL 0
|
# define FENNEC_HAS_BUILTIN_IS_FINAL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Inconsistent with dynamic intrinsics, requires a massive table for static intrinsics
|
// Inconsistent without intrinsics
|
||||||
#if __has_builtin(__is_fundamental)
|
#if __has_builtin(__is_function)
|
||||||
# define FENNEC_HAS_BUILTIN_IS_FUNDAMENTAL 1
|
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 1
|
||||||
# define FENNEC_BUILTIN_IS_FUNDAMENTAL(arg) __is_fundamental(arg)
|
# define FENNEC_BUILTIN_IS_FUNCTION(arg) __is_function(arg)
|
||||||
#else
|
#else
|
||||||
# define FENNEC_HAS_BUILTIN_IS_FUNDAMENTAL 0
|
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Inconsistent without intrinsics
|
||||||
|
#if __has_builtin(__is_object)
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_OBJECT 1
|
||||||
|
# define FENNEC_BUILTIN_IS_OBJECT(arg) __is_object(arg)
|
||||||
|
#else
|
||||||
|
# define FENNEC_HAS_BUILTIN_IS_FUNCTION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Inconsistent without intrinsics
|
// Inconsistent without intrinsics
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
/// - \subpage fennec_lang_conditional_types
|
/// - \subpage fennec_lang_conditional_types
|
||||||
/// - \subpage fennec_lang_numeric_transforms
|
/// - \subpage fennec_lang_numeric_transforms
|
||||||
/// - \subpage fennec_lang_metasequences
|
/// - \subpage fennec_lang_metasequences
|
||||||
|
/// - \subpage fennec_lang_type_identity
|
||||||
/// - \subpage fennec_lang_type_sequences
|
/// - \subpage fennec_lang_type_sequences
|
||||||
/// - \subpage fennec_lang_type_traits
|
/// - \subpage fennec_lang_type_traits
|
||||||
/// - \subpage fennec_lang_type_transforms
|
/// - \subpage fennec_lang_type_transforms
|
||||||
|
|||||||
@@ -51,6 +51,12 @@
|
|||||||
/// \ref fennec::replace_first_element "typename replace_first_element<ClassT, SubT, OriginT, RestT...>::type"<br>
|
/// \ref fennec::replace_first_element "typename replace_first_element<ClassT, SubT, OriginT, RestT...>::type"<br>
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \copydoc fennec::replace_first_element
|
/// \copydoc fennec::replace_first_element
|
||||||
|
///
|
||||||
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
|
/// \ref fennec::is_unique "is_unique<TypesT...>::value"<br>
|
||||||
|
/// \ref fennec::is_unique_v "is_unique_v<TypesT...>"
|
||||||
|
/// <td width="50%" style="vertical-align: top">
|
||||||
|
/// \copydoc fennec::is_unique
|
||||||
/// </table>
|
/// </table>
|
||||||
///
|
///
|
||||||
|
|
||||||
@@ -59,6 +65,12 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
template<typename...TypesT> struct type_sequence {};
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::first_element ===============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Get the first element of a template parameter pack
|
/// \brief Get the first element of a template parameter pack
|
||||||
/// \tparam TypesT the Parameter Pack
|
/// \tparam TypesT the Parameter Pack
|
||||||
@@ -69,8 +81,20 @@ template<typename...TypesT> struct first_element : detail::_first_element<TypesT
|
|||||||
template<typename...TypesT> using first_element_t = typename first_element<TypesT...>::type;
|
template<typename...TypesT> using first_element_t = typename first_element<TypesT...>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::nth_element =================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Gets the type of the nth element of the type sequence `TypesT...`
|
||||||
|
/// \tparam n The index in the type sequence
|
||||||
|
/// \tparam TypesT The type sequence
|
||||||
template<size_t n, typename...TypesT> struct nth_element : detail::_nth_element<n, 0, TypesT...> {};
|
template<size_t n, typename...TypesT> struct nth_element : detail::_nth_element<n, 0, TypesT...> {};
|
||||||
|
|
||||||
|
template<size_t n, typename...TypesT> using nth_element_t = nth_element<n, TypesT...>::type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::replace_first_element =======================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
|
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
|
||||||
@@ -84,6 +108,99 @@ template<
|
|||||||
struct replace_first_element<ClassT<OriginT, RestT...>, SubT> // Specialization
|
struct replace_first_element<ClassT<OriginT, RestT...>, SubT> // Specialization
|
||||||
{ using type = ClassT<SubT, RestT...>; }; // Definition
|
{ using type = ClassT<SubT, RestT...>; }; // Definition
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::max_element_size ============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Gets the max value of the size of each type in the sequence, i.e. `max(sizeof(Ts)...)`
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename...Ts> struct max_element_size : detail::_max_element_size<0, Ts...> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `max_element_size<Ts...>::value`
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename...Ts> constexpr size_t max_element_size_v = max_element_size<Ts...>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::find_element ================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Finds the index of `T` in `Ts`, if `T` is not found, results in `sizeof...(Ts)`
|
||||||
|
/// \tparam T The type to find
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename T, typename...Ts> struct find_element : detail::_find_element<0, T, Ts...> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `find_element<T, Ts...>::value`
|
||||||
|
/// \tparam T The type to find
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename T, typename...Ts> constexpr size_t find_element_v = find_element<T, Ts...>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::search_element ==============================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Find the first element in `TypesT...` that satisfies `SearchT<T>`
|
||||||
|
/// \tparam SearchT A type that satisfies `template<typename>` and contains `static constexpr bool value;` to use for searching
|
||||||
|
/// \tparam TypesT The type sequence to search
|
||||||
|
template<template<typename> typename SearchT, typename...TypesT> struct search_element : detail::_search_element<SearchT, TypesT...> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `search_element_t<T, Ts...>::type`
|
||||||
|
/// \tparam SearchT A type that satisfies `template<typename>` and contains `static constexpr bool value;` to use for searching
|
||||||
|
/// \tparam TypesT The type sequence to search
|
||||||
|
template<template<typename> typename SearchT, typename...TypesT> using search_element_t = search_element<SearchT, TypesT...>::type;
|
||||||
|
|
||||||
|
|
||||||
|
template<template<typename, typename...> typename, typename, typename...> struct search_element_args;
|
||||||
|
|
||||||
|
template<template<typename, typename...> typename SearchT, typename...TypesT, typename...ArgsT>
|
||||||
|
struct search_element_args<SearchT, type_sequence<ArgsT...>, TypesT...>
|
||||||
|
: detail::_search_element_args<SearchT, detail::_type_sequence<ArgsT...>, TypesT...> {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::contains_element ============================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Checks if the type sequence `Ts...` contains `T`
|
||||||
|
/// \tparam T The type to find
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename T, typename...Ts> struct contains_element : bool_constant<(is_same_v<T, Ts> or ...)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `contains_element_v<T, Ts...>::value`
|
||||||
|
/// \tparam T The type to find
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename T, typename...Ts> constexpr bool contains_element_v = contains_element<T, Ts...>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_unique ===================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Checks if all types in a type sequence are unique
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename...Ts> struct is_unique : false_type {};
|
||||||
|
|
||||||
|
// Single type case
|
||||||
|
template<typename T> struct is_unique<T> : true_type {};
|
||||||
|
|
||||||
|
// Recursion case
|
||||||
|
template<typename T, typename...Ts> requires(not is_same_v<T, Ts> && ...)
|
||||||
|
struct is_unique<T, Ts...> : is_unique<Ts...> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for `is_unique<Ts...>::value`
|
||||||
|
/// \tparam Ts The type sequence to check
|
||||||
|
template<typename...Ts> constexpr bool is_unique_v = is_unique<Ts...>::value;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -360,7 +360,7 @@
|
|||||||
/// \ref fennec::is_nothrow_move_constructible "is_nothrow_move_constructible<ClassT, ArgsT...>::value"<br>
|
/// \ref fennec::is_nothrow_move_constructible "is_nothrow_move_constructible<ClassT, ArgsT...>::value"<br>
|
||||||
/// \ref fennec::is_nothrow_move_constructible_v "is_nothrow_move_constructible_v<ClassT, ArgsT...>"
|
/// \ref fennec::is_nothrow_move_constructible_v "is_nothrow_move_constructible_v<ClassT, ArgsT...>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \movedetails fennec::is_move_constructible
|
/// \copydetails fennec::is_move_constructible
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_assignable "is_assignable<ClassT, ArgsT...>::value"<br>
|
/// \ref fennec::is_assignable "is_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
@@ -390,7 +390,7 @@
|
|||||||
/// \ref fennec::is_nothrow_move_assignable "is_nothrow_move_assignable<ClassT, ArgsT...>::value"<br>
|
/// \ref fennec::is_nothrow_move_assignable "is_nothrow_move_assignable<ClassT, ArgsT...>::value"<br>
|
||||||
/// \ref fennec::is_nothrow_move_assignable_v "is_nothrow_move_assignable_v<ClassT, ArgsT...>"
|
/// \ref fennec::is_nothrow_move_assignable_v "is_nothrow_move_assignable_v<ClassT, ArgsT...>"
|
||||||
/// <td width="50%" style="vertical-align: top">
|
/// <td width="50%" style="vertical-align: top">
|
||||||
/// \movedetails fennec::is_move_assignable
|
/// \copydetails fennec::is_move_assignable
|
||||||
///
|
///
|
||||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||||
/// \ref fennec::is_destructible "is_destructible<ClassT, ArgsT...>::value"<br>
|
/// \ref fennec::is_destructible "is_destructible<ClassT, ArgsT...>::value"<br>
|
||||||
@@ -446,7 +446,7 @@ constexpr inline bool is_constant_evaluated() noexcept {
|
|||||||
// fennec::is_void =====================================================================================================
|
// fennec::is_void =====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of type void
|
/// \brief Check if \p T is of type void
|
||||||
///
|
///
|
||||||
/// \details Stores a boolean value in `is_void::value`, representing whether the provided type is of base type void.
|
/// \details Stores a boolean value in `is_void::value`, representing whether the provided type is of base type void.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -454,7 +454,7 @@ template<typename T> struct is_void
|
|||||||
: detail::_is_void<remove_cvr_t<T>>{};
|
: detail::_is_void<remove_cvr_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_void<T>::value```
|
/// \brief Shorthand for ```is_void<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
|
template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
|
||||||
|
|
||||||
@@ -463,7 +463,7 @@ template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
|
|||||||
// fennec::is_null_pointer =============================================================================================
|
// fennec::is_null_pointer =============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of type nullptr_t
|
/// \brief Check if \p T is of type nullptr_t
|
||||||
///
|
///
|
||||||
/// \details Stores a boolean value in `is_null_pointer::value`, representing whether the provided type is of base type nullptr_t.
|
/// \details Stores a boolean value in `is_null_pointer::value`, representing whether the provided type is of base type nullptr_t.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -471,7 +471,7 @@ template<typename T> struct is_null_pointer
|
|||||||
: detail::_is_null_pointer<remove_cvr_t<T>>{};
|
: detail::_is_null_pointer<remove_cvr_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_null_pointer<T>::value```
|
/// \brief Shorthand for ```is_null_pointer<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::value;
|
template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::value;
|
||||||
|
|
||||||
@@ -482,7 +482,7 @@ template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::va
|
|||||||
#ifdef FENNEC_BUILTIN_IS_ARRAY
|
#ifdef FENNEC_BUILTIN_IS_ARRAY
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of an array type
|
/// \brief Check if \p T is of an array type
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_array
|
template<typename T> struct is_array
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_ARRAY(T)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_ARRAY(T)> {};
|
||||||
@@ -490,7 +490,7 @@ template<typename T> struct is_array
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of an array type
|
/// \brief Check if \p T is of an array type
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_array
|
template<typename T> struct is_array
|
||||||
: false_type {};
|
: false_type {};
|
||||||
@@ -506,25 +506,72 @@ template<typename T> struct is_array<T[]>
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_array<T>::value```
|
/// \brief Shorthand for ```is_array<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_array_v = is_array<T>::value;
|
template<typename T> constexpr bool_t is_array_v = is_array<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_enum ====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is an enum
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_enum
|
||||||
|
: bool_constant<FENNEC_BUILTIN_IS_ENUM(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a class
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr size_t is_enum_v = is_enum<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_union ====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a union
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_union
|
||||||
|
: bool_constant<FENNEC_BUILTIN_IS_UNION(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a class
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr size_t is_union_v = is_union<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_class ====================================================================================================
|
// fennec::is_class ====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is a class
|
/// \brief Check if \p T is a class
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_class
|
template<typename T> struct is_class
|
||||||
: bool_constant<FENNEC_BUILTIN_IS_CLASS(T)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CLASS(T)> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is a class
|
/// \brief Check if \p T is a class
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr size_t is_class_v = is_class<T>::value;
|
template<typename T> constexpr size_t is_class_v = is_class<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_function ====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a class
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_function
|
||||||
|
: bool_constant<FENNEC_BUILTIN_IS_FUNCTION(T)> {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is a class
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr size_t is_function_v = is_function<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Integral Types ======================================================================================================
|
// Integral Types ======================================================================================================
|
||||||
|
|
||||||
|
|
||||||
@@ -532,7 +579,7 @@ template<typename T> constexpr size_t is_class_v = is_class<T>::value;
|
|||||||
// fennec::is_bool =====================================================================================================
|
// fennec::is_bool =====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of type bool
|
/// \brief Check if \p T is of type bool
|
||||||
///
|
///
|
||||||
/// \details Stores a boolean value in `is_bool::value`, representing whether the provided type is of base type bool.
|
/// \details Stores a boolean value in `is_bool::value`, representing whether the provided type is of base type bool.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -540,12 +587,16 @@ template<typename T> struct is_bool
|
|||||||
: detail::_is_bool<remove_cvr_t<T>>{};
|
: detail::_is_bool<remove_cvr_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_bool<T>::value```
|
/// \brief Shorthand for ```is_bool<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
|
template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_integral =================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of an integral
|
/// \brief Check if \p T is of an integral
|
||||||
///
|
///
|
||||||
/// \details Stores a boolean value in `is_integral::value`, representing whether the provided type is of a base integer type.
|
/// \details Stores a boolean value in `is_integral::value`, representing whether the provided type is of a base integer type.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -553,13 +604,17 @@ template<typename T> struct is_integral
|
|||||||
: detail::_is_integral<remove_cvr_t<T>> {};
|
: detail::_is_integral<remove_cvr_t<T>> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_integral<T>::value```
|
/// \brief Shorthand for ```is_integral<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
|
template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_signed =================================================================================================
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of a signed integral
|
/// \brief Check if \p T is of a signed integral
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
|
/// \details Checks if type `T` is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -567,13 +622,17 @@ template<typename T> struct is_signed
|
|||||||
: detail::_is_signed<remove_cvr_t<T>> {};
|
: detail::_is_signed<remove_cvr_t<T>> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_signed<T>::value```
|
/// \brief Shorthand for ```is_signed<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
|
template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fennec::is_unsigned =================================================================================================
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of an unsigned integral
|
/// \brief Check if \p T is of an unsigned integral
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
|
/// \details Checks if type `T` is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -581,7 +640,7 @@ template<typename T> struct is_unsigned
|
|||||||
: detail::_is_unsigned<remove_cvr_t<T>> {};
|
: detail::_is_unsigned<remove_cvr_t<T>> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_unsigned<T>::value```
|
/// \brief Shorthand for ```is_unsigned<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
|
template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
|
||||||
|
|
||||||
@@ -590,15 +649,15 @@ template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
|
|||||||
// Floating Point Types ================================================================================================
|
// Floating Point Types ================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of a floating point type
|
/// \brief Check if \p T is of a floating point type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
/// \details Stores a boolean value in `is_floating_point::value`, representing whether the provided type is of a base floating point type.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_floating_point
|
template<typename T> struct is_floating_point
|
||||||
: detail::_is_floating_point<remove_cvr_t<T>>{};
|
: detail::_is_floating_point<remove_cvr_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_floating_point<T>::value```
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
|
template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
|
||||||
|
|
||||||
@@ -606,24 +665,69 @@ template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T>
|
|||||||
// Pointer Types =======================================================================================================
|
// Pointer Types =======================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is of a floating point type
|
/// \brief Check if \p T is of a pointer type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
/// \details Stores a boolean value in `is_pointer::value`, representing whether the provided type is of a base pointer type.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_pointer
|
template<typename T> struct is_pointer
|
||||||
: detail::_is_pointer<remove_cvr_t<T>>{};
|
: detail::_is_pointer<remove_cvr_t<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_floating_point<T>::value```
|
/// \brief Shorthand for ```is_pointer<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
|
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
// Reference Types =======================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is of a floating point type
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_reference
|
||||||
|
: detail::_is_reference<T>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_reference_v = is_reference<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is of a floating point type
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_lvalue_reference
|
||||||
|
: detail::_is_lvalue_reference<T>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_lvalue_reference_v = is_lvalue_reference<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is of a floating point type
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_rvalue_reference
|
||||||
|
: detail::_is_rvalue_reference<T>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_rvalue_reference_v = is_rvalue_reference<T> {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Arithmetic Types ====================================================================================================
|
// Arithmetic Types ====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is an arithmetic type
|
/// \brief Check if \p T is an arithmetic type
|
||||||
///
|
///
|
||||||
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
@@ -631,21 +735,38 @@ template<typename T> struct is_arithmetic
|
|||||||
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
|
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_arithmetic<T>::value```
|
/// \brief Shorthand for ```is_arithmetic<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
|
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Arithmetic Types ====================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Check if \p T is an arithmetic type
|
||||||
|
///
|
||||||
|
/// \details Checks if type `T` is a built-in type with arithmetic operators and store it in `is_same::value`.
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> struct is_scalar
|
||||||
|
: bool_constant<is_arithmetic_v<T> or is_enum_v<T> or is_pointer_v<T>>{};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Shorthand for ```is_scalar<T>::value```
|
||||||
|
/// \tparam T type to check
|
||||||
|
template<typename T> constexpr bool_t is_scalar_v = is_scalar<T>::value;
|
||||||
|
|
||||||
|
|
||||||
// fennec::is_fundamental ==============================================================================================
|
// fennec::is_fundamental ==============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if \p T is a fundamental type, i.e. arithmetic, void, or nullptr_t
|
/// \brief Check if \p T is a fundamental type, i.e. arithmetic, void, or nullptr_t
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_fundamental
|
template<typename T> struct is_fundamental
|
||||||
: bool_constant<is_arithmetic_v<T> || is_void_v<T> || is_null_pointer_v<T>>{};
|
: bool_constant<is_arithmetic_v<T> || is_void_v<T> || is_null_pointer_v<T>>{};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_fundamental<T>::value```
|
/// \brief Shorthand for ```is_fundamental<T>::value```
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::value;
|
template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::value;
|
||||||
|
|
||||||
@@ -653,7 +774,7 @@ template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::valu
|
|||||||
// fennec::is_same =====================================================================================================
|
// fennec::is_same =====================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if the two types are identical
|
/// \brief Check if the two types are identical
|
||||||
///
|
///
|
||||||
/// \details Checks if `T0` and `T1` are identical and store it in `is_same::value`
|
/// \details Checks if `T0` and `T1` are identical and store it in `is_same::value`
|
||||||
/// \tparam T0 first type to check
|
/// \tparam T0 first type to check
|
||||||
@@ -664,7 +785,7 @@ template<typename T0, typename T1> struct is_same : false_type {};
|
|||||||
template<typename T> struct is_same<T, T> : true_type {};
|
template<typename T> struct is_same<T, T> : true_type {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for ```is_same<T0, T1>::value```
|
/// \brief Shorthand for ```is_same<T0, T1>::value```
|
||||||
/// \tparam T0 first type to check
|
/// \tparam T0 first type to check
|
||||||
/// \tparam T1 second type to check
|
/// \tparam T1 second type to check
|
||||||
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
|
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
|
||||||
@@ -672,63 +793,63 @@ template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1>
|
|||||||
// fennec::is_complete ==============================================================================================
|
// fennec::is_complete ==============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if type `T` is complete
|
/// \brief Check if type `T` is complete
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if `T`
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_complete : detail::_is_complete<T>::type {};
|
template<typename T> struct is_complete : detail::_is_complete<T>::type {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `is_complete<TypeT0, TypeT1>::value`
|
/// \brief Shorthand for `is_complete<TypeT0, TypeT1>::value`
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_complete_v = is_complete<T>{};
|
template<typename T> constexpr bool_t is_complete_v = is_complete<T>{};
|
||||||
|
|
||||||
// fennec::is_iterable ==============================================================================================
|
// fennec::is_iterable ==============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if type `T` is iterable
|
/// \brief Check if type `T` is iterable
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if `T`
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_iterable : decltype(detail::_is_iterable<T>(0)) {};
|
template<typename T> struct is_iterable : decltype(detail::_is_iterable<T>(0)) {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `is_iterable<TypeT0, TypeT1>::value`
|
/// \brief Shorthand for `is_iterable<TypeT0, TypeT1>::value`
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_iterable_v = is_iterable<T>{};
|
template<typename T> constexpr bool_t is_iterable_v = is_iterable<T>{};
|
||||||
|
|
||||||
// fennec::is_indexable ==============================================================================================
|
// fennec::is_indexable ==============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if type `T` is indexable
|
/// \brief Check if type `T` is indexable
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if `T`
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_indexable : decltype(detail::_is_indexable<T>(0)) {};
|
template<typename T> struct is_indexable : decltype(detail::_is_indexable<T>(0)) {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `is_indexable<TypeT0, TypeT1>::value`
|
/// \brief Shorthand for `is_indexable<TypeT0, TypeT1>::value`
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_indexable_v = is_indexable<T>{};
|
template<typename T> constexpr bool_t is_indexable_v = is_indexable<T>{};
|
||||||
|
|
||||||
// fennec::is_mappable ==============================================================================================
|
// fennec::is_mappable ==============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if type `T` is mappable
|
/// \brief Check if type `T` is mappable
|
||||||
///
|
///
|
||||||
/// \details Checks if `T`
|
/// \details Checks if `T`
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> struct is_mappable : decltype(detail::_is_mappable<T>(0)) {};
|
template<typename T> struct is_mappable : decltype(detail::_is_mappable<T>(0)) {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `is_mappable<TypeT0, TypeT1>::value`
|
/// \brief Shorthand for `is_mappable<TypeT0, TypeT1>::value`
|
||||||
/// \tparam T type to check
|
/// \tparam T type to check
|
||||||
template<typename T> constexpr bool_t is_mappable_v = is_mappable<T>{};
|
template<typename T> constexpr bool_t is_mappable_v = is_mappable<T>{};
|
||||||
|
|
||||||
// fennec::is_convertible ==============================================================================================
|
// fennec::is_convertible ==============================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief check if type `T0` can be converted `T1`
|
/// \brief Check if type `T0` can be converted `T1`
|
||||||
///
|
///
|
||||||
/// \details Checks if `TypeT0`
|
/// \details Checks if `TypeT0`
|
||||||
/// \tparam FromT First type
|
/// \tparam FromT First type
|
||||||
@@ -737,7 +858,7 @@ template<typename FromT, typename ToT> struct is_convertible
|
|||||||
: bool_constant<FENNEC_BUILTIN_IS_CONVERTIBLE(FromT, ToT)> {};
|
: bool_constant<FENNEC_BUILTIN_IS_CONVERTIBLE(FromT, ToT)> {};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief shorthand for `can_convert<TypeT0, TypeT1>::value`
|
/// \brief Shorthand for `can_convert<TypeT0, TypeT1>::value`
|
||||||
/// \param FromT First type
|
/// \param FromT First type
|
||||||
/// \param ToT Second type
|
/// \param ToT Second type
|
||||||
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
|
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
|
||||||
@@ -779,7 +900,7 @@ template<typename ClassT> struct is_default_constructible
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Shorthand for `is_default_constructible<ClassT>::value`
|
/// \brief Shorthand for `is_default_constructible<ClassT>::value`
|
||||||
template<typename ClassT, typename...ArgsT> constexpr bool_t is_default_constructible_v = is_default_constructible<ClassT>{};
|
template<typename ClassT> constexpr bool_t is_default_constructible_v = is_default_constructible<ClassT>{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -213,6 +213,8 @@ namespace fennec
|
|||||||
|
|
||||||
using bool_t = bool; ///< \brief A conditional type
|
using bool_t = bool; ///< \brief A conditional type
|
||||||
|
|
||||||
|
using byte_t = unsigned char; ///< \brief A type capable of holding a single byte
|
||||||
|
|
||||||
using char_t = char; ///< \brief A type capable of holding an ascii value
|
using char_t = char; ///< \brief A type capable of holding an ascii value
|
||||||
using schar_t = signed char; ///< \brief A type with the size of a char, capable of holding a signed 8-bit integer
|
using schar_t = signed char; ///< \brief A type with the size of a char, capable of holding a signed 8-bit integer
|
||||||
using uchar_t = unsigned char; ///< \brief A type with the size of a char, capable of holding an unsigned 8-bit integer
|
using uchar_t = unsigned char; ///< \brief A type with the size of a char, capable of holding an unsigned 8-bit integer
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <fennec/platform/interface/fwd.h>
|
#include <fennec/platform/interface/fwd.h>
|
||||||
#include <fennec/platform/interface/window.h>
|
#include <fennec/platform/interface/window.h>
|
||||||
#include <fennec/rtti/enable.h>
|
#include <fennec/rtti/enable.h>
|
||||||
|
#include <fennec/rtti/singleton.h>
|
||||||
#include <fennec/rtti/detail/_this_t.h>
|
#include <fennec/rtti/detail/_this_t.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -62,12 +63,12 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
class platform {
|
class platform : singleton<platform*> {
|
||||||
public:
|
public:
|
||||||
using shared_object = struct shared_object;
|
using shared_object = struct shared_object;
|
||||||
using symbol = void*;
|
using symbol = void*;
|
||||||
|
|
||||||
platform() = default;
|
platform();
|
||||||
virtual ~platform() = default;
|
virtual ~platform() = default;
|
||||||
platform(const platform&) = delete;
|
platform(const platform&) = delete;
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ public:
|
|||||||
void initialize() override;
|
void initialize() override;
|
||||||
|
|
||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
|
|
||||||
|
FENNEC_RTTI_CLASS_ENABLE(unix_platform) {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ public:
|
|||||||
symbol find_symbol(shared_object* obj, const cstring& name) override;
|
symbol find_symbol(shared_object* obj, const cstring& name) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
FENNEC_RTTI_CLASS_ENABLE(platform) {
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
#define FENNEC_RTTI_CLASS_ENABLE(...) \
|
#define FENNEC_RTTI_CLASS_ENABLE(...) \
|
||||||
public: \
|
public: \
|
||||||
using super_class_list = fennec::typelist<__VA_ARGS__>; \
|
using super_class_list = fennec::typelist<__VA_ARGS__>; \
|
||||||
virtual fennec::type get_type() { return fennec::type::get_from_instance(this); } \
|
virtual inline fennec::type get_type() const { return fennec::type::get_from_instance(this); } \
|
||||||
FENNEC_DEFINE_THIS_T; \
|
FENNEC_DEFINE_THIS_T; \
|
||||||
private: \
|
private: \
|
||||||
FENNEC_CLASS_STATIC_CONSTRUCTOR(_init_reflection)
|
FENNEC_CLASS_STATIC_CONSTRUCTOR(_init_reflection)
|
||||||
|
|||||||
@@ -31,4 +31,17 @@
|
|||||||
#ifndef FENNEC_RTTI_FORWARD_H
|
#ifndef FENNEC_RTTI_FORWARD_H
|
||||||
#define FENNEC_RTTI_FORWARD_H
|
#define FENNEC_RTTI_FORWARD_H
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class function;
|
||||||
|
struct vtypelist;
|
||||||
|
template<typename...> struct typelist;
|
||||||
|
|
||||||
|
struct type;
|
||||||
|
struct type_data;
|
||||||
|
struct type_storage;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif // FENNEC_RTTI_FORWARD_H
|
#endif // FENNEC_RTTI_FORWARD_H
|
||||||
52
include/fennec/rtti/singleton.h
Normal file
52
include/fennec/rtti/singleton.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file singleton.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_RTTI_SINGLETON_H
|
||||||
|
#define FENNEC_RTTI_SINGLETON_H
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct singleton {
|
||||||
|
static T& instance() requires(is_pointer_v<T>) {
|
||||||
|
static T instance = nullptr;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static T& instance() requires(is_default_constructible_v<T> and not is_pointer_v<T>) {
|
||||||
|
static T instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_RTTI_SINGLETON_H
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
#include <fennec/string/string.h>
|
#include <fennec/string/string.h>
|
||||||
#include <fennec/memory/pointers.h>
|
#include <fennec/memory/pointers.h>
|
||||||
#include <fennec/rtti/typeid.h>
|
#include <fennec/rtti/typeid.h>
|
||||||
#include <fennec/rtti/typelist.h>
|
#include <fennec/rtti/forward.h>
|
||||||
#include <fennec/rtti/detail/_type_name.h>
|
#include <fennec/rtti/detail/_type_name.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
|
|||||||
85
include/fennec/rtti/type_registry.h
Normal file
85
include/fennec/rtti/type_registry.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file type_registry.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_RTTI_TYPE_REGISTRY_H
|
||||||
|
#define FENNEC_RTTI_TYPE_REGISTRY_H
|
||||||
|
#include <fennec/containers/priority_queue.h>
|
||||||
|
#include <fennec/rtti/type.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename BaseT, typename...ArgsT>
|
||||||
|
class type_registry {
|
||||||
|
public:
|
||||||
|
using ctor_t = BaseT (*)(ArgsT&&...);
|
||||||
|
|
||||||
|
struct entry {
|
||||||
|
size_t priority;
|
||||||
|
type type;
|
||||||
|
ctor_t ctor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct compare {
|
||||||
|
bool operator()(const entry& a, const entry& b) const {
|
||||||
|
return a.priority > b.priority and a.ctor < b.ctor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using entrylist_t = priority_queue<entry, compare>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static void register_type(size_t priority = 0) {
|
||||||
|
_global_list().emplace(
|
||||||
|
priority,
|
||||||
|
type::get<T>(),
|
||||||
|
_constructor_helper<ArgsT...>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const entrylist_t& get_type_list() {
|
||||||
|
return _global_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static entrylist_t& _global_list() {
|
||||||
|
static entrylist_t list;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static BaseT* _constructor_helper(ArgsT&&...args) {
|
||||||
|
return new T(fennec::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_RTTI_TYPE_REGISTRY_H
|
||||||
@@ -32,13 +32,23 @@
|
|||||||
#define FENNEC_RTTI_TYPELIST_H
|
#define FENNEC_RTTI_TYPELIST_H
|
||||||
|
|
||||||
#include <fennec/lang/types.h>
|
#include <fennec/lang/types.h>
|
||||||
|
#include <fennec/rtti/type.h>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct vtypelist {
|
||||||
|
virtual ~vtypelist() = default;
|
||||||
|
virtual dynarray<type> get() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename...TypesT>
|
template<typename...TypesT>
|
||||||
struct typelist {
|
struct typelist : vtypelist {
|
||||||
static constexpr size_t size = sizeof...(TypesT);
|
static constexpr size_t size = sizeof...(TypesT);
|
||||||
|
|
||||||
|
virtual dynarray<type> get() {
|
||||||
|
return { type::get<TypesT>()... };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ Library and Template Library.
|
|||||||
| tuple | 🚧 | 🚧 |
|
| tuple | 🚧 | 🚧 |
|
||||||
| optional | ✅ | ✅ |
|
| optional | ✅ | ✅ |
|
||||||
| variant | ⛔ | ⛔ |
|
| variant | ⛔ | ⛔ |
|
||||||
| any | ⛔ | ⛔ |
|
| generic (`std::any`) | ⛔ | ⛔ |
|
||||||
| bitset | ⛔ | ⛔ |
|
| bitset | ⛔ | ⛔ |
|
||||||
| array | ✅ | ✅ |
|
| array | ✅ | ✅ |
|
||||||
| dynarray (`std::vector`) | 🚧 | 🚧 |
|
| dynarray (`std::vector`) | 🚧 | 🚧 |
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ See:
|
|||||||
| is_null_pointer | ✅ | ✅ |
|
| is_null_pointer | ✅ | ✅ |
|
||||||
| is_integral | ✅ | ✅ |
|
| is_integral | ✅ | ✅ |
|
||||||
| is_floating_point | ✅ | ✅ |
|
| is_floating_point | ✅ | ✅ |
|
||||||
| is_array | ✅ | 🚧 |
|
| is_array | ✅ | 🚧 |
|
||||||
| is_enum | ⛔ | ⛔ |
|
| is_enum | ⛔ | ⛔ |
|
||||||
| is_union | ⛔ | ⛔ |
|
| is_union | ⛔ | ⛔ |
|
||||||
| is_class | ✅ | ✅ |
|
| is_class | ✅ | ✅ |
|
||||||
|
|||||||
@@ -21,6 +21,11 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
platform::platform() {
|
||||||
|
assertf(instance() == nullptr, "Attempted to instantiate multiple platforms.");
|
||||||
|
instance() = this;
|
||||||
|
}
|
||||||
|
|
||||||
void platform::initialize() {
|
void platform::initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user