diff --git a/source/Core/Common.hpp b/source/Core/Common.hpp index 8092317..fd8da6c 100644 --- a/source/Core/Common.hpp +++ b/source/Core/Common.hpp @@ -47,6 +47,12 @@ /// Exploits [[deprecated("warning")]] to log template instantiations #define LANGULUS_TEMPLATE() [[deprecated("template intantiation")]] +/// Checks if code is executed at compile-time +/// @attention must be followed by {...} +/// TODO when we transition to C++23, we should replace +/// if (std::is_constant_evaluated()) statements with if consteval ones +#define IF_CONSTEXPR() if (std::is_constant_evaluated()) + #if LANGULUS_COMPILER(MSVC) /// Force no inlining #define LANGULUS_NOINLINE() __declspec(noinline) @@ -432,6 +438,9 @@ namespace Langulus or requires (FROM& from) { static_cast(from); } or ::std::convertible_to; + template + concept Enum = ::std::is_enum_v; + template concept Fundamental = ::std::is_fundamental_v; @@ -505,6 +514,11 @@ namespace Langulus and Complete...> and (Inner::Convertible, Decay> and ...); + /// Check if the origin T is an enum type + template + concept Enum = Complete...> + and (Inner::Enum> and ...); + /// Check if the origin T is a fundamental type template concept Fundamental = Complete...> diff --git a/source/Core/Utilities.hpp b/source/Core/Utilities.hpp index 500f941..93ac77b 100644 --- a/source/Core/Utilities.hpp +++ b/source/Core/Utilities.hpp @@ -291,226 +291,4 @@ namespace Langulus return r > 0 ? v + (alignment - r) : v; } - /// Wrapper for memcpy - /// @tparam TO - destination memory type (deducible) - /// @tparam FROM - source memory type (deducible) - /// @param to - [out] destination memory - /// @param from - source of data to copy - template - LANGULUS(INLINED) - void CopyMemory(TO* to, const FROM* from) noexcept { - static_assert(CT::Void - or CT::Sparse - or CT::POD - or ::std::is_trivial_v, - "TO must be either pointer, reflected as POD, or trivial. " - "(you can suppress this error by casting pointer to void*)"); - - static_assert(CT::Void - or(CT::Same and CT::Sparse == CT::Sparse), - "TO and FROM must be the exact same types" - "(you can suppress this error by casting pointer to void*)"); - - if constexpr (CT::Void) - LANGULUS_ERROR("Bytecount not specified when copying void pointers"); - - ::std::memcpy( - static_cast(to), - static_cast(from), - sizeof(TO) - ); - } - - /// Wrapper for memcpy - /// @tparam TO - destination memory type (deducible) - /// @tparam FROM - source memory type (deducible) - /// @param to - [out] destination memory - /// @param from - source of data to copy - /// @param count - number of elements to copy - /// @attention count becomes bytecount, when TO is void - template - LANGULUS(INLINED) - void CopyMemory(TO* to, const FROM* from, const Count& count) noexcept { - static_assert(CT::Void - or CT::Sparse - or CT::POD - or ::std::is_trivial_v, - "TO must be either pointer, reflected as POD, or trivial. " - "(you can suppress this error by casting pointer to void*)"); - - static_assert(CT::Void - or(CT::Same and CT::Sparse == CT::Sparse), - "TO and FROM must be the exact same types" - "(you can suppress this error by casting pointer to void*)"); - - if constexpr (CT::Void) { - ::std::memcpy( - static_cast(to), - static_cast(from), - count - ); - } - else { - ::std::memcpy( - static_cast(to), - static_cast(from), - sizeof(TO) * count - ); - } - } - - /// Wrapper for memset - /// @tparam TO - destination memory type (deducible) - /// @tparam FILLER - value to fill in with - /// @param to - [out] destination memory - template - LANGULUS(INLINED) - void FillMemory(TO* to) noexcept { - static_assert(CT::Void - or CT::Sparse - or CT::POD - or ::std::is_trivial_v, - "TO must be either pointer, reflected as POD, or trivial. " - "(you can suppress this error by casting to void*)"); - - static_assert(FILLER - or CT::Nullifiable - or CT::Void - or CT::Sparse - or CT::Fundamental, - "Filling with zeroes requires the type to be reflected as nullifiable, " - "or be a pointer/fundamental (you can suppress this error by casting to void*)"); - - if constexpr (CT::Void) - LANGULUS_ERROR("Bytecount not specified when filling void pointer"); - - ::std::memset(static_cast(to), FILLER, sizeof(TO)); - } - - /// Wrapper for memset - /// @tparam TO - destination memory type (deducible) - /// @tparam FILLER - value to fill in with - /// @param to - [out] destination memory - /// @param count - number of elements to fill - /// @attention count becomes bytecount, when TO is void - template - LANGULUS(INLINED) - void FillMemory(TO* to, const Count& count) noexcept { - static_assert(CT::Void - or CT::Sparse - or CT::POD - or ::std::is_trivial_v, - "TO must be either pointer, reflected as POD, or trivial. " - "(you can suppress this error by casting to void*)"); - - static_assert(FILLER - or CT::Nullifiable - or CT::Void - or CT::Sparse - or CT::Fundamental, - "Filling with zeroes requires the type to be reflected as nullifiable, " - "or be a pointer/fundamental (you can suppress this error by casting to void*)"); - - if constexpr (CT::Void) - ::std::memset(static_cast(to), FILLER, count); - else - ::std::memset(static_cast(to), FILLER, sizeof(TO) * count); - } - - /// Wrapper for memset 0 - /// @tparam TO - destination memory type (deducible) - /// @param to - [out] destination memory - template - LANGULUS(INLINED) - void ZeroMemory(TO* to) noexcept { - return FillMemory<0>(to); - } - - /// Wrapper for memset 0 - /// @tparam TO - destination memory type (deducible) - /// @param to - [out] destination memory - /// @param count - number of elements to fill - /// @attention count becomes bytecount, when TO is void - template - LANGULUS(INLINED) - void ZeroMemory(TO* to, const Count& count) noexcept { - return FillMemory<0>(to, count); - } - - /// Wrapper for memmove - /// @tparam TO - destination memory type (deducible) - /// @tparam FROM - source memory type (deducible) - /// @param to - [out] destination memory - /// @param from - source of data to move - template - LANGULUS(INLINED) - void MoveMemory(TO* to, const FROM* from) noexcept { - static_assert(CT::Void - or CT::Sparse - or CT::POD - or ::std::is_trivial_v, - "TO must be either pointer, reflected as POD, or trivial. " - "(You can suppress this error by casting pointer to void*)"); - - static_assert(CT::Void - or(CT::Same and CT::Sparse == CT::Sparse), - "TO and FROM must be the exact same types" - "(you can suppress this error by casting pointer to void*)"); - - if constexpr (CT::Void) - LANGULUS_ERROR("Bytecount not specified when filling void pointer"); - - ::std::memmove( - static_cast(to), - static_cast(from), - sizeof(TO) - ); - - #if LANGULUS(PARANOID) - TODO() // zero old memory, but beware - `from` and `to` might overlap - #endif - } - - /// Wrapper for memmove - /// @tparam TO - destination memory type (deducible) - /// @tparam FROM - source memory type (deducible) - /// @param to - [out] destination memory - /// @param from - source of data to move - /// @param count - number of elements to move - /// @attention count becomes bytecount, when TO is void - template - LANGULUS(INLINED) - void MoveMemory(TO* to, const FROM* from, const Count& count) noexcept { - static_assert(CT::Void - or CT::Sparse - or CT::POD - or ::std::is_trivial_v, - "TO must be either pointer, reflected as POD, or trivial. " - "(You can suppress this error by casting pointer to void*)"); - - static_assert(CT::Void - or(CT::Same and CT::Sparse == CT::Sparse), - "TO and FROM must be the exact same types" - "(you can suppress this error by casting pointer to void*)"); - - if constexpr (CT::Void) { - ::std::memmove( - static_cast(to), - static_cast(from), - count - ); - } - else { - ::std::memmove( - static_cast(to), - static_cast(from), - sizeof(TO) * count - ); - } - - #if LANGULUS(PARANOID) - TODO() // zero old memory, but beware - `from` and `to` might overlap - #endif - } - } // namespace Langulus