diff --git a/ProjectOptions.cmake b/ProjectOptions.cmake index 4bf21e4..ccec983 100644 --- a/ProjectOptions.cmake +++ b/ProjectOptions.cmake @@ -55,7 +55,15 @@ macro(lefticus_tools_setup_options) option(lefticus_tools_ENABLE_SANITIZER_THREAD "Enable thread sanitizer" OFF) option(lefticus_tools_ENABLE_SANITIZER_MEMORY "Enable memory sanitizer" OFF) option(lefticus_tools_ENABLE_UNITY_BUILD "Enable unity builds" OFF) - option(lefticus_tools_ENABLE_CLANG_TIDY "Enable clang-tidy" ON) + + # Only enable clang-tidy by default if we're targetting clang. + # Why? because you might have other flags and settings that don't work + # Between clang and gcc + if (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*") + option(lefticus_tools_ENABLE_CLANG_TIDY "Enable clang-tidy" ON) + else() + option(lefticus_tools_ENABLE_CLANG_TIDY "Enable clang-tidy" OFF) + endif() option(lefticus_tools_ENABLE_CPPCHECK "Enable cpp-check analysis" OFF) option(lefticus_tools_ENABLE_PCH "Enable precompiled headers" OFF) option(lefticus_tools_ENABLE_CACHE "Enable ccache" ON) diff --git a/cmake/Hardening.cmake b/cmake/Hardening.cmake index c11727f..e47a59c 100644 --- a/cmake/Hardening.cmake +++ b/cmake/Hardening.cmake @@ -17,9 +17,12 @@ macro( set(NEW_CXX_DEFINITIONS "${NEW_CXX_DEFINITIONS} -D_GLIBCXX_ASSERTIONS") message(STATUS "*** GLIBC++ Assertions (vector[], string[], ...) enabled") + # Hardening requires some amount of optimization enabled + if (CMAKE_BUILD_TYPE MATCHES ".*Rel.*") set(NEW_COMPILE_OPTIONS "${NEW_COMPILE_OPTIONS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3") message(STATUS "*** g++/clang _FORTIFY_SOURCE=3 enabled") + endif() # check_cxx_compiler_flag(-fpie PIE) #if(PIE) diff --git a/include/lefticus/tools/consteval_invoke.hpp b/include/lefticus/tools/consteval_invoke.hpp index 04f1ecf..27074cf 100644 --- a/include/lefticus/tools/consteval_invoke.hpp +++ b/include/lefticus/tools/consteval_invoke.hpp @@ -1,3 +1,31 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + + #ifndef LEFTICUS_TOOLS_CONSTEVAL_INVOKE_HPP #define LEFTICUS_TOOLS_CONSTEVAL_INVOKE_HPP diff --git a/include/lefticus/tools/flat_map.hpp b/include/lefticus/tools/flat_map.hpp index 34827a3..777119f 100644 --- a/include/lefticus/tools/flat_map.hpp +++ b/include/lefticus/tools/flat_map.hpp @@ -1,3 +1,30 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + #ifndef TOOLS_FLAT_MAP_HPP #define TOOLS_FLAT_MAP_HPP diff --git a/include/lefticus/tools/flat_map_adapter.hpp b/include/lefticus/tools/flat_map_adapter.hpp index b75e912..e03940c 100644 --- a/include/lefticus/tools/flat_map_adapter.hpp +++ b/include/lefticus/tools/flat_map_adapter.hpp @@ -1,3 +1,31 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + + #ifndef LEFTICUS_TOOLS_FLAT_MAP_HPP #define LEFTICUS_TOOLS_FLAT_MAP_HPP diff --git a/include/lefticus/tools/lambda_coroutines.hpp b/include/lefticus/tools/lambda_coroutines.hpp index 946cfb6..e3e2caa 100644 --- a/include/lefticus/tools/lambda_coroutines.hpp +++ b/include/lefticus/tools/lambda_coroutines.hpp @@ -1,3 +1,31 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + + #ifndef LAMBDA_COROUTINES_HPP #define LAMBDA_COROUTINES_HPP diff --git a/include/lefticus/tools/non_promoting_ints.hpp b/include/lefticus/tools/non_promoting_ints.hpp index 5b75480..67b412a 100644 --- a/include/lefticus/tools/non_promoting_ints.hpp +++ b/include/lefticus/tools/non_promoting_ints.hpp @@ -1,3 +1,31 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + + #ifndef LEFTICUS_TOOLS_NON_PROMOTING_INTS_HPP #define LEFTICUS_TOOLS_NON_PROMOTING_INTS_HPP diff --git a/include/lefticus/tools/simple_stack_flat_map.hpp b/include/lefticus/tools/simple_stack_flat_map.hpp index 5c09435..16fbf63 100644 --- a/include/lefticus/tools/simple_stack_flat_map.hpp +++ b/include/lefticus/tools/simple_stack_flat_map.hpp @@ -1,3 +1,31 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + + #ifndef TOOLS_SIMPLE_STACK_FLAT_MAP_HPP #define TOOLS_SIMPLE_STACK_FLAT_MAP_HPP diff --git a/include/lefticus/tools/simple_stack_string.hpp b/include/lefticus/tools/simple_stack_string.hpp index 666e500..529756a 100644 --- a/include/lefticus/tools/simple_stack_string.hpp +++ b/include/lefticus/tools/simple_stack_string.hpp @@ -1,3 +1,31 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + + #ifndef LEFTICUS_TOOLS_SIMPLE_STACK_STRING_HPP #define LEFTICUS_TOOLS_SIMPLE_STACK_STRING_HPP diff --git a/include/lefticus/tools/simple_stack_vector.hpp b/include/lefticus/tools/simple_stack_vector.hpp index 2e7ea5a..f1387a4 100644 --- a/include/lefticus/tools/simple_stack_vector.hpp +++ b/include/lefticus/tools/simple_stack_vector.hpp @@ -1,3 +1,31 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + + #ifndef LEFTICUS_TOOLS_SIMPLE_STACK_VECTOR_HPP #define LEFTICUS_TOOLS_SIMPLE_STACK_VECTOR_HPP diff --git a/include/lefticus/tools/static_views.hpp b/include/lefticus/tools/static_views.hpp index cb8ce78..6e18924 100644 --- a/include/lefticus/tools/static_views.hpp +++ b/include/lefticus/tools/static_views.hpp @@ -1,3 +1,31 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + + #ifndef LEFTICUS_TOOLS_STATIC_VIEWS_HPP #define LEFTICUS_TOOLS_STATIC_VIEWS_HPP diff --git a/include/lefticus/tools/strong_types.hpp b/include/lefticus/tools/strong_types.hpp new file mode 100644 index 0000000..9613e6e --- /dev/null +++ b/include/lefticus/tools/strong_types.hpp @@ -0,0 +1,166 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + + +// +// Created by jason on 3/12/24. +// + +#ifndef LEFTICUS_TOOLS_STRONG_TYPES_HPP +#define LEFTICUS_TOOLS_STRONG_TYPES_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace lefticus::tools { +template +concept addable = requires(LHS lhs, RHS rhs) { add(lhs, rhs); }; + +template +concept subtractable = requires(LHS lhs, RHS rhs) { subtract(lhs, rhs); }; + +template +concept multipliable = requires(LHS lhs, RHS rhs) { multiply(lhs, rhs); }; + +template +concept dividable = requires(LHS lhs, RHS rhs) { divide(lhs, rhs); }; + +template +concept negatable = requires(LHS lhs) { negate(lhs); }; + +template +concept orderable = requires(LHS lhs, RHS rhs) { order(lhs, rhs); }; + +template +concept equatable = requires(LHS lhs, RHS rhs) { equate(lhs, rhs); }; + +template +concept casts_to = requires(const From &from) { + { + casts(from) + } -> std::same_as; +}; + + +template constexpr void null_validator(const Underlying &) {} + +template> struct strong_alias +{ + template + constexpr explicit strong_alias(Param &&...param) + requires std::is_constructible_v + : data(std::forward(param)...) + { + Validator(data); + } + + [[nodiscard]] constexpr const Underlying &get() const & noexcept { return data; } + [[nodiscard]] constexpr Underlying &&get() && noexcept { return std::move(data); } + [[nodiscard]] constexpr Underlying &get() & noexcept { return data; } + + [[nodiscard]] auto operator<=>(const strong_alias &rhs) const noexcept + requires(orderable) + = default; + + [[nodiscard]] bool operator==(const strong_alias &rhs) const noexcept + requires(equatable) + = default; + + template + [[nodiscard]] constexpr auto operator<=>(const strong_alias &rhs) const noexcept + requires(orderable>) + { + return data <=> rhs.get(); + } + template + [[nodiscard]] constexpr bool operator==(const strong_alias &rhs) const noexcept + requires(equatable>) + { + return data == rhs.get(); + } + +private: + Underlying data; +}; + +template +[[nodiscard]] constexpr auto operator-(LHS &&lhs) noexcept(noexcept(-lhs.get())) -> decltype(negate(lhs)) + requires(negatable) +{ + return decltype(negate(lhs)){ std::forward(lhs).get() }; +} + +template +[[nodiscard]] constexpr auto operator+(LHS &&lhs, RHS &&rhs) noexcept(noexcept(lhs.get() + rhs.get())) + -> decltype(add(lhs, rhs)) + requires(addable) +{ + return decltype(add(lhs, rhs)){ std::forward(lhs).get() + std::forward(rhs).get() }; +} + +template +[[nodiscard]] constexpr auto operator-(LHS &&lhs, RHS &&rhs) noexcept(noexcept(lhs.get() - rhs.get())) + -> decltype(subtract(lhs, rhs)) + requires(subtractable) +{ + return decltype(subtract(lhs, rhs)){ std::forward(lhs).get() - std::forward(rhs).get() }; +} + +template +[[nodiscard]] constexpr auto operator*(LHS &&lhs, RHS &&rhs) noexcept(noexcept(lhs.get() * rhs.get())) + -> decltype(multiply(lhs, rhs)) + requires(multipliable) +{ + return decltype(multiply(lhs, rhs)){ std::forward(lhs).get() * std::forward(rhs).get() }; +} + +template +[[nodiscard]] constexpr auto operator/(LHS &&lhs, RHS &&rhs) noexcept(noexcept(lhs.get() / rhs.get())) + -> decltype(divide(lhs, rhs)) + requires(dividable) +{ + return decltype(divide(lhs, rhs)){ std::forward(lhs).get() / std::forward(rhs).get() }; +} + +template +[[nodiscard]] constexpr auto strong_cast(From &&from) -> To + requires(casts_to) +{ + return To{ std::forward(from).get() }; +} + +}// namespace lefticus::tools + +#endif \ No newline at end of file diff --git a/include/lefticus/tools/type_lists.hpp b/include/lefticus/tools/type_lists.hpp new file mode 100644 index 0000000..78aa89a --- /dev/null +++ b/include/lefticus/tools/type_lists.hpp @@ -0,0 +1,105 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + +#ifndef LEFTICUS_TOOLS_TYPE_LISTS_HPP +#define LEFTICUS_TOOLS_TYPE_LISTS_HPP + + +#include + +namespace lefticus::tools { + +template struct type_pair +{ + using first_type = First; + using second_type = Second; +}; + +template struct type_list +{ +}; + +template<> struct type_list<> +{ +}; + +template struct type_list +{ + using first_type = First; +}; + +template auto last_type(type_list) -> decltype((type_list{}, ...))::first_type; + +template auto first_type(type_list) -> First; + +template +auto nth_type_helper(type_list) -> First + requires(N == 0); + +// This is an optimization if we detect it's just the last one, so we don't +// recurse further +template +auto nth_type_helper(type_list list) -> decltype(last_type(list)) + requires(N > 0 && N == sizeof...(T) - 1); + +template +auto nth_type_helper(type_list list) -> decltype(nth_type_helper(type_list{})) + requires(N > 0 && N != sizeof...(T)); + +template auto nth_type(type_list list) -> decltype(nth_type_helper(list)); + +template using nth_t = decltype(nth_type(T{})); + +template +auto split_n_helper(type_list last, type_list) -> type_pair, type_list> + requires(N == 0); + +template +auto split_n_helper(type_list, type_list) + -> decltype(split_n_helper(type_list{}, type_list{})) + requires(N > 0); + +template +auto split_n(type_list list) -> decltype(split_n_helper(type_list<>{}, list)); + +template using split_n_t = decltype(split_n(T{})); + +template auto join(type_list, type_list) -> type_list; + +template using join_t = decltype(join(LHS{}, RHS{})); + +template +auto sub(type_list) -> + typename split_n_t>::second_type>::first_type; + +template using sub_t = decltype(sub(T{})); + + +}// namespace lefticus::tools + + +#endif// LEFTICUS_TOOLS_TYPE_LISTS_HPP diff --git a/include/lefticus/tools/utility.hpp b/include/lefticus/tools/utility.hpp index 85f4d2f..4152fd7 100644 --- a/include/lefticus/tools/utility.hpp +++ b/include/lefticus/tools/utility.hpp @@ -1,5 +1,33 @@ -#ifndef TOOLS_UTILITY_HPP -#define TOOLS_UTILITY_HPP +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +*/ + + +#ifndef LEFTICUS_TOOLS_UTILITY_HPP +#define LEFTICUS_TOOLS_UTILITY_HPP #include @@ -31,4 +59,4 @@ template template pair(First f, Second s) -> pair; }// namespace lefticus::tools -#endif// TOOLS_UTILITY_HPP +#endif// LEFTICUS_TOOLS_UTILITY_HPP diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b8166e8..3c6a21a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -81,7 +81,9 @@ add_constexpr_test_executables( simple_stack_vector_tests.cpp static_views_tests.cpp simple_stack_string_tests.cpp - flat_map_tests.cpp) + flat_map_tests.cpp + type_lists_tests.cpp + strong_types_tests.cpp) target_link_libraries( "constexpr_tests" PRIVATE lefticus::tools @@ -128,3 +130,5 @@ test_header_compiles(non_promoting_ints.hpp) test_header_compiles(simple_stack_flat_map.hpp) test_header_compiles(static_views.hpp) test_header_compiles(utility.hpp) +test_header_compiles(strong_types.hpp) +test_header_compiles(type_lists.hpp) diff --git a/test/strong_types_tests.cpp b/test/strong_types_tests.cpp new file mode 100644 index 0000000..0b5645e --- /dev/null +++ b/test/strong_types_tests.cpp @@ -0,0 +1,179 @@ +// +// Created by jason on 3/12/24. +// + +#include +#include + +#ifdef CATCH_CONFIG_RUNTIME_STATIC_REQUIRE +#define CONSTEXPR +#else +// NOLINTNEXTLINE +#define CONSTEXPR constexpr +#endif + +// we could have auto detected the capabilities, by using requires +// but that would have enabled more operations than we wanted. + +struct Point +{ + float x; + float y; + [[nodiscard]] constexpr auto operator<=>(const Point &) const noexcept = default; +}; + +[[nodiscard]] constexpr Point operator*(Point lhs, float scalar) noexcept +{ + return Point{ lhs.x * scalar, lhs.y * scalar }; +} + +[[nodiscard]] constexpr Point operator*(float scalar, Point p) noexcept { return Point{ p.x * scalar, p.y * scalar }; } + +[[nodiscard]] constexpr Point operator+(Point lhs, Point rhs) noexcept { return Point{ lhs.x + rhs.x, lhs.y + rhs.y }; } + +[[nodiscard]] constexpr Point operator-(Point lhs, Point rhs) noexcept { return Point{ lhs.x - rhs.x, lhs.y - rhs.y }; } + + +/* +using Player_Position = strong_alias; +using Offset = strong_alias; + +auto plus(Player_Position, Offset) -> Player_Position; +auto plus(Offset, Player_Position) -> Player_Position; +auto minus(Player_Position, Offset) -> Player_Position; +auto minus(Offset, Player_Position) -> Player_Position; +auto equate(Player_Position, Player_Position) -> bool; +auto order(Player_Position, Player_Position) -> bool; +*/ + +using Position = lefticus::tools::strong_alias; +using Time = lefticus::tools::strong_alias; + +auto order(Position, Position) -> bool; +auto order(Time, Time) -> bool; + +using Player1_Position = lefticus::tools::strong_alias; +using Player1_Velocity = lefticus::tools::strong_alias; +using Player1_Displacement = lefticus::tools::strong_alias; + +auto add(Player1_Position, Player1_Displacement) -> Player1_Position; +auto add(Player1_Displacement, Player1_Position) -> Player1_Position; +auto multiply(Time, Player1_Velocity) -> Player1_Displacement; +auto multiply(Player1_Velocity, Time) -> Player1_Displacement; + +using Player2_Position = lefticus::tools::strong_alias; +using Player2_Velocity = lefticus::tools::strong_alias; +using Player2_Displacement = lefticus::tools::strong_alias; + +auto add(Player2_Position, Player2_Displacement) -> Player2_Position; +auto add(Player2_Displacement, Player2_Position) -> Player2_Position; +auto multiply(Time, Player2_Velocity) -> Player2_Displacement; +auto multiply(Player2_Velocity, Time) -> Player2_Displacement; + +auto casts(Player1_Position) -> Position; +auto casts(Player2_Position) -> Position; + +auto update_position(auto position, auto velocity, Time t) { return position + velocity * t; } + +struct Avatar +{ +}; +struct Player1 +{ +}; +struct Player2 +{ +}; + +void draw(Avatar, Position) {} + +auto get_avatar(Player1, Time) -> Avatar { return {}; } +auto get_avatar(Player2, Time) -> Avatar { return {}; } + +auto get_position(Player1) -> Player1_Position { return Player1_Position{}; } +auto get_position(Player2) -> Player2_Position { return Player2_Position{}; } + +auto get_displacement(Player1) -> Player1_Displacement { return Player1_Displacement{}; } +auto get_displacement(Player2) -> Player2_Displacement { return Player2_Displacement{}; } + +auto get_velocity(Player1) -> Player1_Velocity { return Player1_Velocity{}; } +auto get_velocity(Player2) -> Player2_Velocity { return Player2_Velocity{}; } + +auto get_player1() -> Player1 { return {}; } +auto get_player2() -> Player2 { return {}; } + +void draw_players(Time t) +{ + auto do_draw = [t](const auto &player) { + draw(get_avatar(player, t), strong_cast(update_position(get_position(player), get_velocity(player), t))); + }; + + do_draw(get_player1()); + do_draw(get_player1()); +} + +using Pattern = lefticus::tools::strong_alias; +using Directory = + lefticus::tools::strong_alias; + +using File = + lefticus::tools::strong_alias; + +auto order(File, File) -> bool; +auto equate(File, File) -> bool; +auto order(Directory, Directory) -> bool; +auto equate(Directory, Directory) -> bool; +auto order(Pattern, Pattern) -> bool; +auto equate(Pattern, Pattern) -> bool; +auto divide(Directory, Directory) -> Directory; +auto divide(Directory, File) -> File; + +bool matches([[maybe_unused]] const Pattern &pattern, [[maybe_unused]] const std::filesystem::path &path) +{ + return false; +} + +std::optional find_first_file(const Directory &dir, const Pattern &pattern) +{ + for (const auto &path : std::filesystem::directory_iterator{ dir.get() } | std::views::filter([](const auto &f) { + return std::filesystem::is_regular_file(f); + }) | std::views::filter(std::bind_front(matches, pattern))) { + return File{ path }; + } + + return {}; +} + + +template consteval bool types_equatable() +{ + return requires(LHS lhs, RHS rhs) { lhs == rhs; }; +} + +TEST_CASE("Strong types sanity checks") +{ + CONSTEXPR Player1_Position p{ 2.0f, 3.0f }; + CONSTEXPR Player1_Velocity v{ -1.0f, 2.0f }; + CONSTEXPR Time t{ 4.0f }; + + STATIC_REQUIRE(std::is_same_v); + STATIC_REQUIRE(std::is_same_v); + STATIC_REQUIRE(std::is_same_v); + + STATIC_REQUIRE(!types_equatable()); + STATIC_REQUIRE(!types_equatable()); + STATIC_REQUIRE(!types_equatable()); + + + STATIC_REQUIRE((p + (t * v)).get() == Point{ 2.0f + (-1.0f * 4.0f), 3.0f + (2.0f * 4.0f) }); + + auto f = find_first_file(Directory{ "/home/jason" }, Pattern{ "*.txt" }); + + draw_players(Time{ 4.3f }); +} diff --git a/test/type_lists_tests.cpp b/test/type_lists_tests.cpp new file mode 100644 index 0000000..da30093 --- /dev/null +++ b/test/type_lists_tests.cpp @@ -0,0 +1,57 @@ +#include +#include + + +TEST_CASE("Test nth type getter") +{ + STATIC_REQUIRE(std::is_same_v>>); + STATIC_REQUIRE(std::is_same_v>>); + STATIC_REQUIRE(std::is_same_v>>); + + STATIC_REQUIRE(std::is_same_v>>); +} + + +TEST_CASE("Test split_n type list splitter") +{ + STATIC_REQUIRE(std::is_same_v< + lefticus::tools::type_pair, lefticus::tools::type_list>, + lefticus::tools::split_n_t<0, lefticus::tools::type_list>>); + + STATIC_REQUIRE(std::is_same_v< + lefticus::tools::type_pair, lefticus::tools::type_list>, + lefticus::tools::split_n_t<1, lefticus::tools::type_list>>); + + STATIC_REQUIRE(std::is_same_v< + lefticus::tools::type_pair, lefticus::tools::type_list>, + lefticus::tools::split_n_t<2, lefticus::tools::type_list>>); + + STATIC_REQUIRE(std::is_same_v< + lefticus::tools::type_pair, lefticus::tools::type_list<>>, + lefticus::tools::split_n_t<3, lefticus::tools::type_list>>); +} + + +TEST_CASE("Test join type list joiner") +{ + STATIC_REQUIRE(std::is_same_v, + lefticus::tools::join_t, lefticus::tools::type_list>>); + + STATIC_REQUIRE(std::is_same_v, + lefticus::tools::join_t, lefticus::tools::type_list>>); + STATIC_REQUIRE(std::is_same_v, + lefticus::tools::join_t, lefticus::tools::type_list>>); + + STATIC_REQUIRE(std::is_same_v, + lefticus::tools::join_t, lefticus::tools::type_list<>>>); +} + +TEST_CASE("Test sub type list sub list splitter") +{ + STATIC_REQUIRE(std::is_same_v, + lefticus::tools::sub_t<0, 0, lefticus::tools::type_list>>); + STATIC_REQUIRE(std::is_same_v, + lefticus::tools::sub_t<0, 1, lefticus::tools::type_list>>); + STATIC_REQUIRE(std::is_same_v, + lefticus::tools::sub_t<1, 2, lefticus::tools::type_list>>); +}