From de681d3cd7db61f327183b52cadc9d3b16d5ff99 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Thu, 23 Apr 2020 14:40:51 -0700 Subject: [PATCH] Improve constexpr-ness of strings --- include/rexy/string_base.hpp | 42 +++++++++++------------------ include/rexy/string_base.tpp | 52 +++++++++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index d892fa5..033c2bf 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -81,11 +81,11 @@ namespace rexy{ constexpr string_intermediary(void); constexpr string_intermediary(rexy::steal data, size_t len); constexpr string_intermediary(rexy::steal data, size_t len, size_t cap); - [[deprecated]] string_intermediary(char* data, size_t len); + [[deprecated]] constexpr string_intermediary(char* data, size_t len); string_intermediary(const char* data, size_t len); [[deprecated]] constexpr string_intermediary(char* data, size_t len, size_t cap); string_intermediary(const char* data); - string_intermediary(rexy::steal); + constexpr string_intermediary(rexy::steal); string_intermediary(size_t len); string_intermediary(size_t len, size_t cap); @@ -99,7 +99,7 @@ namespace rexy{ ~string_intermediary(void); string_intermediary& operator=(const string_intermediary& s); - string_intermediary& operator=(string_intermediary&& s); + constexpr string_intermediary& operator=(string_intermediary&& s); //Copy from c string string_intermediary& operator=(const char* c); //Copy from other string_base @@ -182,19 +182,11 @@ namespace rexy{ static constexpr bool value = std::is_same::type*>()))>::value; }; - //check for member function 'length' - template - struct has_len{ - template - struct check; + template + using enable_if_string = std::enable_if_t<(is_string::value && ...),int>; + template + using enable_if_concrete_string = std::enable_if_t<(is_concrete_string::value && ...),int>; - template - static std::true_type test(check*); - template - static std::false_type test(...); - - static constexpr bool value = std::is_same(0))>::value; - }; template struct appender { @@ -206,39 +198,35 @@ namespace rexy{ void operator()(const string_cat_expr& str); void operator()(const string_base& str); }; - } - template::value && - detail::is_concrete_string::value,int> = 0> + } //namespace detail + template = 0> bool operator==(Str1&& left, Str2&& right){ return left.valid() && right.valid() && left.length() == right.length() && !strcmp(left.get(), right.get()); } - template::value && - detail::is_concrete_string::value,int> = 0> + template = 0> bool operator!=(Str1&& left, Str2&& right){ return !(left == right); } - template::value && - detail::is_string::value,int> = 0> + template = 0> constexpr auto operator+(Left&& l, Right&& r){ return string_cat_expr(std::forward(l), std::forward(r)); } - template::value,int> = 0> + template = 0> constexpr auto operator+(const char* left, Right&& right){ return string_cat_expr(rexy::static_string(left), std::forward(right)); } - template::value,int> = 0> + template = 0> constexpr auto operator+(Left&& left, const char* right){ return rexy::string_cat_expr(std::forward(left), rexy::static_string(right)); } - template::value && - detail::is_string::value,int> = 0> + template = 0, detail::enable_if_string = 0> decltype(auto) operator+=(Left& l, Right&& r){ return l = (l + std::forward(r)); } - template::value,int> = 0> + template = 0> decltype(auto) operator+=(Left& l, const char* r){ return l = (l + r); } diff --git a/include/rexy/string_base.tpp b/include/rexy/string_base.tpp index 7f9147f..27b6f16 100644 --- a/include/rexy/string_base.tpp +++ b/include/rexy/string_base.tpp @@ -26,25 +26,51 @@ #include //max namespace rexy{ - namespace{ - template - constexpr T cx_exchange(T& t, U&& u){ - T old = std::move(t); - t = std::forward(u); - return old; + namespace detail{ + namespace{ + constexpr size_t cx_strlen(char* c){ + size_t i = 0; + for(;c[i];++i); + return i; + } } - } + }//namespace detail + +//std::swap and std::exchange aren't constexpr until c++20 +#if __cplusplus > 201703L + #define cx_swap(...) std::swap(__VA_ARGS__) + #define cx_exchange(...) std::exchange(__VA_ARGS__) +#else + namespace detail{ + namespace{ + template + constexpr void cx_swap(T& a, T& b){ + T tmp = std::move(a); + a = std::move(b); + b = std::move(tmp); + } + template + constexpr T cx_exchange(T& t, U&& u){ + T old = std::move(t); + t = std::forward(u); + return old; + } + } + } //namespace detail + #define cx_swap(...) detail::cx_swap(__VA_ARGS__) + #define cx_exchange(...) detail::cx_exchange(__VA_ARGS__) +#endif template constexpr string_intermediary::string_intermediary(void){} template - string_intermediary::string_intermediary(char* data, size_t len): + /*deprecated*/ constexpr string_intermediary::string_intermediary(char* data, size_t len): string_base(data, len){} template constexpr string_intermediary::string_intermediary(rexy::steal data, size_t len): string_base(data.value(), len){} template - constexpr string_intermediary::string_intermediary(char* data, size_t len, size_t cap): + /*deprecated*/ constexpr string_intermediary::string_intermediary(char* data, size_t len, size_t cap): string_base(data, len, cap){} template constexpr string_intermediary::string_intermediary(rexy::steal data, size_t len, size_t cap): @@ -65,8 +91,8 @@ namespace rexy{ } } template - string_intermediary::string_intermediary(rexy::steal data): - string_base(data.value() ? strlen(data.value()) : 0) + constexpr string_intermediary::string_intermediary(rexy::steal data): + string_base(data.value() ? detail::cx_strlen(data.value()) : 0) { m_data = data.value(); m_length = m_cap; @@ -113,8 +139,8 @@ namespace rexy{ return (*this = std::move(tmp)); } template - string_intermediary& string_intermediary::operator=(string_intermediary&& s){ - std::swap(m_data, s.m_data); + constexpr string_intermediary& string_intermediary::operator=(string_intermediary&& s){ + cx_swap(m_data, s.m_data); m_length = s.m_length; m_cap = s.m_cap; return *this;