Improve constexpr-ness of strings
This commit is contained in:
parent
6c142c990d
commit
de681d3cd7
@ -81,11 +81,11 @@ namespace rexy{
|
||||
constexpr string_intermediary(void);
|
||||
constexpr string_intermediary(rexy::steal<char*> data, size_t len);
|
||||
constexpr string_intermediary(rexy::steal<char*> 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<char*>);
|
||||
constexpr string_intermediary(rexy::steal<char*>);
|
||||
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<std::true_type,decltype(is_string_base(std::declval<typename std::decay<T>::type*>()))>::value;
|
||||
};
|
||||
|
||||
//check for member function 'length'
|
||||
template<class T>
|
||||
struct has_len{
|
||||
template<class U, class V>
|
||||
struct check;
|
||||
template<class... Ts>
|
||||
using enable_if_string = std::enable_if_t<(is_string<Ts>::value && ...),int>;
|
||||
template<class... Ts>
|
||||
using enable_if_concrete_string = std::enable_if_t<(is_concrete_string<Ts>::value && ...),int>;
|
||||
|
||||
template<class U>
|
||||
static std::true_type test(check<U,decltype(&U::length)>*);
|
||||
template<class U>
|
||||
static std::false_type test(...);
|
||||
|
||||
static constexpr bool value = std::is_same<std::true_type,decltype(test<T>(0))>::value;
|
||||
};
|
||||
template<class Targ>
|
||||
struct appender
|
||||
{
|
||||
@ -206,39 +198,35 @@ namespace rexy{
|
||||
void operator()(const string_cat_expr<L,R>& str);
|
||||
void operator()(const string_base& str);
|
||||
};
|
||||
}
|
||||
template<class Str1, class Str2, std::enable_if_t<detail::is_concrete_string<Str1>::value &&
|
||||
detail::is_concrete_string<Str2>::value,int> = 0>
|
||||
} //namespace detail
|
||||
template<class Str1, class Str2, detail::enable_if_concrete_string<Str1,Str2> = 0>
|
||||
bool operator==(Str1&& left, Str2&& right){
|
||||
return left.valid() && right.valid() && left.length() == right.length() && !strcmp(left.get(), right.get());
|
||||
}
|
||||
template<class Str1, class Str2, std::enable_if_t<detail::is_concrete_string<Str1>::value &&
|
||||
detail::is_concrete_string<Str2>::value,int> = 0>
|
||||
template<class Str1, class Str2, detail::enable_if_concrete_string<Str1,Str2> = 0>
|
||||
bool operator!=(Str1&& left, Str2&& right){
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
template<class Left, class Right, std::enable_if_t<detail::is_string<Left>::value &&
|
||||
detail::is_string<Right>::value,int> = 0>
|
||||
template<class Left, class Right, detail::enable_if_string<Left,Right> = 0>
|
||||
constexpr auto operator+(Left&& l, Right&& r){
|
||||
return string_cat_expr(std::forward<Left>(l), std::forward<Right>(r));
|
||||
}
|
||||
template<class Right, std::enable_if_t<detail::is_string<Right>::value,int> = 0>
|
||||
template<class Right, detail::enable_if_string<Right> = 0>
|
||||
constexpr auto operator+(const char* left, Right&& right){
|
||||
return string_cat_expr(rexy::static_string(left), std::forward<Right>(right));
|
||||
}
|
||||
|
||||
template<class Left, std::enable_if_t<detail::is_string<Left>::value,int> = 0>
|
||||
template<class Left, detail::enable_if_string<Left> = 0>
|
||||
constexpr auto operator+(Left&& left, const char* right){
|
||||
return rexy::string_cat_expr(std::forward<Left>(left), rexy::static_string(right));
|
||||
}
|
||||
|
||||
template<class Left, class Right, std::enable_if_t<detail::is_string<Left>::value &&
|
||||
detail::is_string<Right>::value,int> = 0>
|
||||
template<class Left, class Right, detail::enable_if_concrete_string<Left> = 0, detail::enable_if_string<Right> = 0>
|
||||
decltype(auto) operator+=(Left& l, Right&& r){
|
||||
return l = (l + std::forward<Right>(r));
|
||||
}
|
||||
template<class Left, std::enable_if_t<detail::is_string<Left>::value,int> = 0>
|
||||
template<class Left, detail::enable_if_concrete_string<Left> = 0>
|
||||
decltype(auto) operator+=(Left& l, const char* r){
|
||||
return l = (l + r);
|
||||
}
|
||||
|
||||
@ -26,25 +26,51 @@
|
||||
#include <rexy/detail/util.hpp> //max
|
||||
|
||||
namespace rexy{
|
||||
namespace{
|
||||
template<class T, class U = T>
|
||||
constexpr T cx_exchange(T& t, U&& u){
|
||||
T old = std::move(t);
|
||||
t = std::forward<U>(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<class T>
|
||||
constexpr void cx_swap(T& a, T& b){
|
||||
T tmp = std::move(a);
|
||||
a = std::move(b);
|
||||
b = std::move(tmp);
|
||||
}
|
||||
template<class T, class U = T>
|
||||
constexpr T cx_exchange(T& t, U&& u){
|
||||
T old = std::move(t);
|
||||
t = std::forward<U>(u);
|
||||
return old;
|
||||
}
|
||||
}
|
||||
} //namespace detail
|
||||
#define cx_swap(...) detail::cx_swap(__VA_ARGS__)
|
||||
#define cx_exchange(...) detail::cx_exchange(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
template<class Allocator>
|
||||
constexpr string_intermediary<Allocator>::string_intermediary(void){}
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>::string_intermediary(char* data, size_t len):
|
||||
/*deprecated*/ constexpr string_intermediary<Allocator>::string_intermediary(char* data, size_t len):
|
||||
string_base(data, len){}
|
||||
template<class Allocator>
|
||||
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data, size_t len):
|
||||
string_base(data.value(), len){}
|
||||
template<class Allocator>
|
||||
constexpr string_intermediary<Allocator>::string_intermediary(char* data, size_t len, size_t cap):
|
||||
/*deprecated*/ constexpr string_intermediary<Allocator>::string_intermediary(char* data, size_t len, size_t cap):
|
||||
string_base(data, len, cap){}
|
||||
template<class Allocator>
|
||||
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data, size_t len, size_t cap):
|
||||
@ -65,8 +91,8 @@ namespace rexy{
|
||||
}
|
||||
}
|
||||
template<class Allocator>
|
||||
string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data):
|
||||
string_base(data.value() ? strlen(data.value()) : 0)
|
||||
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> 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<class Allocator>
|
||||
string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(string_intermediary&& s){
|
||||
std::swap(m_data, s.m_data);
|
||||
constexpr string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(string_intermediary&& s){
|
||||
cx_swap(m_data, s.m_data);
|
||||
m_length = s.m_length;
|
||||
m_cap = s.m_cap;
|
||||
return *this;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user