diff --git a/CMakeLists.txt b/CMakeLists.txt index 29eb007..0fb16b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,10 @@ set(librexy_VERSION_REVISION 0) set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include) include_directories(BEFORE SYSTEM "${INCLUDE_PATH}") +#find_program(CMAKE_CXX_CPPCHECK NAMES cppcheck) +#if(CMAKE_CXX_CPPCHECK) +# list(APPEND CMAKE_CXX_CPPCHECK "--enable=warning" "--inconclusive" "--force" "--inline-suppr") +#endif() cmake_dependent_option(ENABLE_SHARED "Build shared library" ON "NOT BUILD_HEADER_ONLY" OFF) cmake_dependent_option(ENABLE_SSO "Use small string optimization" ON "NOT BUILD_HEADER_ONLY" ON) diff --git a/include/rexy/allocator.hpp b/include/rexy/allocator.hpp index 3272898..6178d43 100644 --- a/include/rexy/allocator.hpp +++ b/include/rexy/allocator.hpp @@ -20,7 +20,7 @@ #define REXY_DEFAULT_ALLOCATOR_HPP #include //ptrdiff_t, size_t -#include //true_type, false_type, is_constant_evaluated +#include //true_type, false_type #include #include //numeric_limits @@ -37,6 +37,7 @@ #include "rexy.hpp" #include "compat/standard.hpp" +#include "compat/if_consteval.hpp" #include //declval @@ -82,11 +83,7 @@ namespace rexy{ REXY_CPP20_CONSTEXPR pointer allocate(size_type n){ size_type bytes = has_overflow(n) ? std::numeric_limits::max() : n*sizeof(T); - #ifdef __cpp_if_consteval - if consteval{ //} //makes my braces matcher in nano not upset ;) - #else - if(std::is_constant_evaluated()){ - #endif //__cpp_if_consteval + REXY_if_consteval{ std::allocator a; const size_type num_items = n / sizeof(value_type); return a.allocate(num_items); @@ -101,11 +98,7 @@ namespace rexy{ REXY_CPP20_CONSTEXPR void deallocate(pointer p, size_type n){ - #ifdef __cpp_if_consteval - if consteval{ //} //makes my braces matcher in nano not upset ;) - #else - if(std::is_constant_evaluated()){ - #endif + REXY_if_consteval{ std::allocator a; const size_type num_items = n / sizeof(value_type); return a.deallocate(p, num_items); diff --git a/include/rexy/compat/if_consteval.hpp b/include/rexy/compat/if_consteval.hpp new file mode 100644 index 0000000..7fb4a7b --- /dev/null +++ b/include/rexy/compat/if_consteval.hpp @@ -0,0 +1,30 @@ +/** + This file is a part of rexy's general purpose library + Copyright (C) 2022 rexy712 + + 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 . +*/ + +#ifndef REXY_if_consteval + +#if defined(__cpp_if_consteval) + #define REXY_if_consteval if consteval + #define REXY_if_consteval if not consteval +#elif defined(__cpp_lib_is_constant_evaluated) + #include //is_constant_evaluated + #define REXY_if_consteval if(std::is_constant_evaluated()) + #define REXY_if_not_consteval if(!std::is_constant_evaluated()) +#endif //__cpp_if_consteval + +#endif diff --git a/include/rexy/compat/standard.hpp b/include/rexy/compat/standard.hpp index 2b269b6..9f994fe 100644 --- a/include/rexy/compat/standard.hpp +++ b/include/rexy/compat/standard.hpp @@ -29,11 +29,14 @@ #if __cplusplus >= 202300L #define REXY_STANDARD_CPP23 - #elif __cplusplus >= 202002L + #endif + #if __cplusplus >= 202002L #define REXY_STANDARD_CPP20 - #elif __cplusplus >= 201703L + #endif + #if __cplusplus >= 201703L #define REXY_STANDARD_CPP17 - #else //__cplusplus + #endif + #if __cplusplus < 201703L #error "Requires minimum C++17 standard" #endif //__cplusplus diff --git a/include/rexy/concepts/string.hpp b/include/rexy/concepts/string.hpp index d7ed044..503d90d 100644 --- a/include/rexy/concepts/string.hpp +++ b/include/rexy/concepts/string.hpp @@ -29,9 +29,41 @@ namespace rexy{ template class string_cat_expr; + template + class basic_string; + template + class basic_string_view; + + template + struct is_basic_string{ + template + static std::true_type check(const basic_string*); + static std::false_type check(...); + + static constexpr bool value = decltype(check(std::declval*>()))::value; + }; + + template + struct is_basic_string_view{ + template + static std::true_type check(const basic_string_view*); + static std::false_type check(...); + + static constexpr bool value = decltype(check(std::declval*>()))::value; + }; + + template + struct is_basic_string_expr{ + template + static std::true_type check(const string_cat_expr*); + static std::false_type check(...); + + static constexpr bool value = decltype(check(std::declval*>()))::value; + }; template concept BasicString = requires(const T& a){ + requires(is_basic_string::value || is_basic_string_view::value); {std::as_const(a).length()} -> std::convertible_to::size_type>; {std::as_const(a).c_str()} -> std::convertible_to::const_pointer>; {std::as_const(a)[0]} -> std::convertible_to::const_reference>; @@ -39,7 +71,7 @@ namespace rexy{ {std::as_const(a).end()} -> std::convertible_to::const_iterator>; }; template - concept StringExpr = rexy::is_template_type::value; + concept StringExpr = is_basic_string_expr::value; template concept String = BasicString || StringExpr; diff --git a/include/rexy/detail/format/parse_context.tpp b/include/rexy/detail/format/parse_context.tpp index 308d56a..8403322 100644 --- a/include/rexy/detail/format/parse_context.tpp +++ b/include/rexy/detail/format/parse_context.tpp @@ -19,12 +19,13 @@ #ifndef REXY_DETAIL_FORMAT_PARSE_CONTEXT_TPP #define REXY_DETAIL_FORMAT_PARSE_CONTEXT_TPP +#include "../../compat/if_consteval.hpp" + #include "parse_context.hpp" #include "format_error.hpp" #include //size_t -#include //is_constant_evaluated namespace rexy::fmt{ @@ -53,8 +54,10 @@ namespace rexy::fmt{ //error, already in manual mode REXY_THROW_FORMAT_ERROR("Invalid indexing mode switch"); } - if(std::is_constant_evaluated() && arg_index >= arg_count){ - REXY_THROW_FORMAT_ERROR("Missing argument"); + REXY_if_consteval{ + if(arg_index >= arg_count){ + REXY_THROW_FORMAT_ERROR("Missing argument"); + } } return arg_index++; } @@ -64,8 +67,10 @@ namespace rexy::fmt{ //error, already in automatic mode REXY_THROW_FORMAT_ERROR("Invalid indexing mode switch"); } - if(std::is_constant_evaluated() && id >= arg_count){ - REXY_THROW_FORMAT_ERROR("Missing argument"); + REXY_if_consteval{ + if(id >= arg_count){ + REXY_THROW_FORMAT_ERROR("Missing argument"); + } } arg_index = detail::invalid_arg_index; } diff --git a/include/rexy/detail/format/specs_handler.hpp b/include/rexy/detail/format/specs_handler.hpp index 693d62a..26a7717 100644 --- a/include/rexy/detail/format/specs_handler.hpp +++ b/include/rexy/detail/format/specs_handler.hpp @@ -19,7 +19,7 @@ #ifndef REXY_DETAIL_FORMAT_SPECS_HANDLER_HPP #define REXY_DETAIL_FORMAT_SPECS_HANDLER_HPP -#include //is_constant_evaluated +#include "../../compat/if_consteval.hpp" namespace rexy::fmt::detail{ @@ -87,7 +87,7 @@ namespace rexy::fmt::detail{ constexpr cx_format_specs_handler(ParseCtx& pc, dynamic_format_specs& s): dynamic_format_specs_handler(pc, s){ - if(!std::is_constant_evaluated()){ + REXY_if_not_consteval{ throw 0; } } diff --git a/include/rexy/format.hpp b/include/rexy/format.hpp index d634ef7..a54deab 100644 --- a/include/rexy/format.hpp +++ b/include/rexy/format.hpp @@ -22,6 +22,13 @@ #include "string.hpp" #include "string_view.hpp" +#include "compat/standard.hpp" + +#ifndef REXY_STANDARD_CPP20 + //Maybe I'll make it work someday, but not for now + #error "Cannot use formatting library without C++20 support" +#endif + #include "detail/format/standard_types.hpp" #include "detail/format/internal_types.hpp" #include "detail/format/arg_store.hpp" diff --git a/include/rexy/string.hpp b/include/rexy/string.hpp index 1eb95f5..5006c0f 100644 --- a/include/rexy/string.hpp +++ b/include/rexy/string.hpp @@ -26,16 +26,25 @@ namespace rexy{ //new allocated string - using string = basic_string>; - using wstring = basic_string>; + using string = basic_string; + using wstring = basic_string; + using u16string = basic_string; + using u32string = basic_string; +#ifdef __cpp_char8_t + using u8string = basic_string; +#endif #ifndef LIBREXY_HEADER_ONLY extern template class basic_string>; extern template class basic_string>; extern template class basic_string>; extern template class basic_string>; +#ifdef __cpp_char8_t + extern template class basic_string>; #endif +#endif //LIBREXY_HEADER_ONLY + } #ifdef REXY_CX_HASH_HPP diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index 1ec5924..37ed3d9 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -162,8 +162,7 @@ namespace rexy{ }else if(len){ set_islong_flag(false); pointer raw = set_short_ptr(); - if(len) - memcpy(raw, data, sizeof(value_type)*len); + memcpy(raw, data, sizeof(value_type)*len); raw[len] = 0; set_short_length(len); set_short_capacity(cap); diff --git a/include/rexy/traits.hpp b/include/rexy/traits.hpp index fa1d7a3..c8736f6 100644 --- a/include/rexy/traits.hpp +++ b/include/rexy/traits.hpp @@ -30,7 +30,7 @@ namespace rexy{ static std::true_type check(U*); static std::false_type check(...); - static constexpr bool value = std::is_same*>()))>::value; + static constexpr bool value = decltype(check(std::declval*>()))::value; }; template class U> diff --git a/include/rexy/utility.hpp b/include/rexy/utility.hpp index 4065b87..eac98fe 100644 --- a/include/rexy/utility.hpp +++ b/include/rexy/utility.hpp @@ -26,6 +26,7 @@ #include //wcslen #include //char_traits +#include "compat/if_consteval.hpp" #include "rexy.hpp" namespace rexy{ @@ -91,14 +92,14 @@ namespace rexy{ return val > 0 ? val : -val; } -#ifdef __cpp_lib_is_constant_evaluated +#ifdef REXY_if_constexpr template constexpr size_t strlen(const T* c)noexcept{ return std::char_traits::length(c); } template constexpr int strcmp(const T* l, const T* r)noexcept{ - if(!std::is_constant_evaluated()){ + REXY_if_constexpr{ if constexpr(std::is_same_v,char>){ return std::strcmp(l, r); }else if constexpr(std::is_same_v,wchar_t>){ @@ -110,7 +111,7 @@ namespace rexy{ } template constexpr int strncmp(const T* l, const T* r, std::size_t max)noexcept{ - if(!std::is_constant_evaluated()){ + REXY_if_constexpr{ if constexpr(std::is_same_v,char>){ return std::strncmp(l, r, max); }else if constexpr (std::is_same_v,wchar_t>){ @@ -122,7 +123,7 @@ namespace rexy{ } template constexpr int strncmp(const T* l, const T* r, std::size_t max, Compare cmp)noexcept{ - if(!std::is_constant_evaluated()){ + REXY_if_constexpr{ if constexpr(std::is_same_v,char>){ return std::strncmp(l, r, max); }else if constexpr (std::is_same_v,wchar_t>){ @@ -138,7 +139,7 @@ namespace rexy{ return *l - *r; } constexpr void memcpy(void* l, const void* r, size_t n){ - if(!std::is_constant_evaluated()){ + REXY_if_constexpr{ std::memcpy(l, r, n); }else{ char* ld = static_cast(l); @@ -149,7 +150,7 @@ namespace rexy{ } } } -#else //__cpp_lib_is_constant_evaluated +#else // REXY_if_constexpr template constexpr size_t strlen(const T* c)noexcept{ size_t i = 0; @@ -179,7 +180,7 @@ namespace rexy{ } } } -#endif //__cpp_lib_is_constant_evaluated +#endif // REXY_if_constexpr } diff --git a/src/string.cpp b/src/string.cpp index 4ca26a6..530132f 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -25,5 +25,8 @@ namespace rexy{ template class basic_string>; template class basic_string>; template class basic_string>; +#ifdef __cpp_char8_t + template class basic_string>; +#endif }