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(void);
|
||||||
constexpr string_intermediary(rexy::steal<char*> data, size_t len);
|
constexpr string_intermediary(rexy::steal<char*> data, size_t len);
|
||||||
constexpr string_intermediary(rexy::steal<char*> data, size_t len, size_t cap);
|
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);
|
string_intermediary(const char* data, size_t len);
|
||||||
[[deprecated]] constexpr string_intermediary(char* data, size_t len, size_t cap);
|
[[deprecated]] constexpr string_intermediary(char* data, size_t len, size_t cap);
|
||||||
string_intermediary(const char* data);
|
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);
|
||||||
string_intermediary(size_t len, size_t cap);
|
string_intermediary(size_t len, size_t cap);
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ namespace rexy{
|
|||||||
~string_intermediary(void);
|
~string_intermediary(void);
|
||||||
|
|
||||||
string_intermediary& operator=(const string_intermediary& s);
|
string_intermediary& operator=(const string_intermediary& s);
|
||||||
string_intermediary& operator=(string_intermediary&& s);
|
constexpr string_intermediary& operator=(string_intermediary&& s);
|
||||||
//Copy from c string
|
//Copy from c string
|
||||||
string_intermediary& operator=(const char* c);
|
string_intermediary& operator=(const char* c);
|
||||||
//Copy from other string_base
|
//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;
|
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... Ts>
|
||||||
template<class T>
|
using enable_if_string = std::enable_if_t<(is_string<Ts>::value && ...),int>;
|
||||||
struct has_len{
|
template<class... Ts>
|
||||||
template<class U, class V>
|
using enable_if_concrete_string = std::enable_if_t<(is_concrete_string<Ts>::value && ...),int>;
|
||||||
struct check;
|
|
||||||
|
|
||||||
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>
|
template<class Targ>
|
||||||
struct appender
|
struct appender
|
||||||
{
|
{
|
||||||
@ -206,39 +198,35 @@ namespace rexy{
|
|||||||
void operator()(const string_cat_expr<L,R>& str);
|
void operator()(const string_cat_expr<L,R>& str);
|
||||||
void operator()(const string_base& str);
|
void operator()(const string_base& str);
|
||||||
};
|
};
|
||||||
}
|
} //namespace detail
|
||||||
template<class Str1, class Str2, std::enable_if_t<detail::is_concrete_string<Str1>::value &&
|
template<class Str1, class Str2, detail::enable_if_concrete_string<Str1,Str2> = 0>
|
||||||
detail::is_concrete_string<Str2>::value,int> = 0>
|
|
||||||
bool operator==(Str1&& left, Str2&& right){
|
bool operator==(Str1&& left, Str2&& right){
|
||||||
return left.valid() && right.valid() && left.length() == right.length() && !strcmp(left.get(), right.get());
|
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 &&
|
template<class Str1, class Str2, detail::enable_if_concrete_string<Str1,Str2> = 0>
|
||||||
detail::is_concrete_string<Str2>::value,int> = 0>
|
|
||||||
bool operator!=(Str1&& left, Str2&& right){
|
bool operator!=(Str1&& left, Str2&& right){
|
||||||
return !(left == right);
|
return !(left == right);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Left, class Right, std::enable_if_t<detail::is_string<Left>::value &&
|
template<class Left, class Right, detail::enable_if_string<Left,Right> = 0>
|
||||||
detail::is_string<Right>::value,int> = 0>
|
|
||||||
constexpr auto operator+(Left&& l, Right&& r){
|
constexpr auto operator+(Left&& l, Right&& r){
|
||||||
return string_cat_expr(std::forward<Left>(l), std::forward<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){
|
constexpr auto operator+(const char* left, Right&& right){
|
||||||
return string_cat_expr(rexy::static_string(left), std::forward<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){
|
constexpr auto operator+(Left&& left, const char* right){
|
||||||
return rexy::string_cat_expr(std::forward<Left>(left), rexy::static_string(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 &&
|
template<class Left, class Right, detail::enable_if_concrete_string<Left> = 0, detail::enable_if_string<Right> = 0>
|
||||||
detail::is_string<Right>::value,int> = 0>
|
|
||||||
decltype(auto) operator+=(Left& l, Right&& r){
|
decltype(auto) operator+=(Left& l, Right&& r){
|
||||||
return l = (l + std::forward<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){
|
decltype(auto) operator+=(Left& l, const char* r){
|
||||||
return l = (l + r);
|
return l = (l + r);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,25 +26,51 @@
|
|||||||
#include <rexy/detail/util.hpp> //max
|
#include <rexy/detail/util.hpp> //max
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
namespace{
|
namespace detail{
|
||||||
template<class T, class U = T>
|
namespace{
|
||||||
constexpr T cx_exchange(T& t, U&& u){
|
constexpr size_t cx_strlen(char* c){
|
||||||
T old = std::move(t);
|
size_t i = 0;
|
||||||
t = std::forward<U>(u);
|
for(;c[i];++i);
|
||||||
return old;
|
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>
|
template<class Allocator>
|
||||||
constexpr string_intermediary<Allocator>::string_intermediary(void){}
|
constexpr string_intermediary<Allocator>::string_intermediary(void){}
|
||||||
template<class Allocator>
|
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){}
|
string_base(data, len){}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data, size_t len):
|
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data, size_t len):
|
||||||
string_base(data.value(), len){}
|
string_base(data.value(), len){}
|
||||||
template<class Allocator>
|
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){}
|
string_base(data, len, cap){}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data, size_t len, size_t cap):
|
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>
|
template<class Allocator>
|
||||||
string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data):
|
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data):
|
||||||
string_base(data.value() ? strlen(data.value()) : 0)
|
string_base(data.value() ? detail::cx_strlen(data.value()) : 0)
|
||||||
{
|
{
|
||||||
m_data = data.value();
|
m_data = data.value();
|
||||||
m_length = m_cap;
|
m_length = m_cap;
|
||||||
@ -113,8 +139,8 @@ namespace rexy{
|
|||||||
return (*this = std::move(tmp));
|
return (*this = std::move(tmp));
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(string_intermediary&& s){
|
constexpr string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(string_intermediary&& s){
|
||||||
std::swap(m_data, s.m_data);
|
cx_swap(m_data, s.m_data);
|
||||||
m_length = s.m_length;
|
m_length = s.m_length;
|
||||||
m_cap = s.m_cap;
|
m_cap = s.m_cap;
|
||||||
return *this;
|
return *this;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user