Improve string constexpr-ness and cleanup addition operators

This commit is contained in:
rexy712 2020-04-21 19:03:12 -07:00
parent 72f8c0d592
commit a280642cac
3 changed files with 79 additions and 106 deletions

View File

@ -31,7 +31,7 @@ namespace rexy{
public:
template<class U>
steal(U&& u):
constexpr steal(U&& u):
m_val(std::forward<U>(u)){}
steal(const steal&) = delete;
@ -39,10 +39,10 @@ namespace rexy{
steal& operator=(const steal&) = delete;
steal& operator=(steal&&) = delete;
T&& value(void){
constexpr T&& value(void){
return std::forward<T>(m_val);
}
const T& value(void)const{
constexpr const T& value(void)const{
return m_val;
}
};

View File

@ -47,7 +47,7 @@ namespace rexy{
constexpr string_base(char* data, size_t len, size_t cap):
m_length(len), m_cap(cap), m_data(data){}
//Copy ctor (do nothing)
string_base(const string_base&){}
constexpr string_base(const string_base&){}
~string_base(void) = default;
public:
@ -63,7 +63,7 @@ namespace rexy{
constexpr operator char*(void){return m_data;}
constexpr operator const char*(void)const{return m_data;}
//true if m_data is not null
constexpr operator bool(void)const{return m_data;}
constexpr bool valid(void)const{return m_data;}
char& operator[](size_t i);
const char& operator[](size_t i)const;
@ -78,12 +78,12 @@ namespace rexy{
using allocator_type = Allocator;
public:
string_intermediary(void) = default;
string_intermediary(rexy::steal<char*> data, size_t len);
string_intermediary(rexy::steal<char*> data, size_t len, size_t cap);
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);
string_intermediary(const char* data, size_t len);
[[deprecated]] 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(rexy::steal<char*>);
string_intermediary(size_t len);
@ -91,7 +91,7 @@ namespace rexy{
//normal copy and move ctors
string_intermediary(const string_intermediary& b);
string_intermediary(string_intermediary&& s);
constexpr string_intermediary(string_intermediary&& s);
string_intermediary(const string_base& b);
@ -137,6 +137,20 @@ namespace rexy{
constexpr const Left& left(void)const;
constexpr const Right& right(void)const;
};
template<class Left, class Right>
string_cat_expr(Left&, Right&) -> string_cat_expr<Left&,Right&>;
template<class Left, class Right>
string_cat_expr(const Left&, const Right&) -> string_cat_expr<const Left&,const Right&>;
template<class Left, class Right>
string_cat_expr(Left&&,Right&&) -> string_cat_expr<Left,Right>;
template<class Left, class Right>
string_cat_expr(Left&,Right&&) -> string_cat_expr<Left&,Right>;
template<class Left, class Right>
string_cat_expr(const Left&,Right&&) -> string_cat_expr<const Left&,Right>;
template<class Left, class Right>
string_cat_expr(Left&&,Right&) -> string_cat_expr<Left,Right&>;
template<class Left, class Right>
string_cat_expr(Left&&,const Right&) -> string_cat_expr<Left,const Right&>;
class static_string : public string_base
{
@ -155,11 +169,11 @@ namespace rexy{
namespace detail{
std::true_type is_string_helper(string_expr);
std::true_type is_string_helper(string_expr*);
std::false_type is_string_helper(...);
template<class T>
struct is_string{
static constexpr bool value = std::is_same<std::true_type,decltype(is_string_helper(std::declval<T>()))>::value;
static constexpr bool value = std::is_same<std::true_type,decltype(is_string_helper(std::declval<typename std::decay<T>::type*>()))>::value;
};
std::true_type is_string_base(string_base*);
std::false_type is_string_base(...);
@ -167,13 +181,6 @@ namespace rexy{
struct is_concrete_string{
static constexpr bool value = std::is_same<std::true_type,decltype(is_string_base(std::declval<typename std::decay<T>::type*>()))>::value;
};
template<class... Args>
std::true_type is_tuple_helper(std::tuple<Args...>);
std::false_type is_tuple_helper(...);
template<class T>
struct is_tuple{
static constexpr bool value = std::is_same<std::true_type,decltype(is_tuple_helper(std::declval<T>()))>::value;
};
//check for member function 'length'
template<class T>
@ -200,6 +207,41 @@ namespace rexy{
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>
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>
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>
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>
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>
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>
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>
decltype(auto) operator+=(Left& l, const char* r){
return l = (l + r);
}
}
#include <rexy/string_base.tpp>
@ -209,86 +251,6 @@ namespace{
return rexy::static_string(str, len);
}
}
template<class Str1, class Str2, typename std::enable_if<rexy::detail::is_concrete_string<Str1>::value&&rexy::detail::is_concrete_string<Str2>::value,void>::type* = nullptr>
bool operator==(Str1&& left, Str2&& right){
return left && right && left.length() == right.length() && !strcmp(left.get(), right.get());
}
template<class Str1, class Str2, typename std::enable_if<rexy::detail::is_concrete_string<Str1>::value&&rexy::detail::is_concrete_string<Str2>::value,void>::type* = nullptr>
bool operator!=(Str1&& left, Str2&& right){
return !(left == right);
}
template<class Right, typename std::enable_if<rexy::detail::is_string<Right>::value && std::is_rvalue_reference<Right&&>::value,void>::type* = nullptr>
constexpr auto operator+(const char* left, Right&& right){
return rexy::string_cat_expr<rexy::static_string,typename std::remove_reference<Right>::type>(rexy::static_string(left), std::move(right));
}
template<class Right, typename std::enable_if<rexy::detail::is_string<Right>::value && !std::is_rvalue_reference<Right&&>::value,void>::type* = nullptr>
constexpr auto operator+(const char* left, Right&& right){
return rexy::string_cat_expr<rexy::static_string,decltype(std::forward<Right>(right))>(rexy::static_string(left), std::forward<Right>(right));
}
template<class Left, typename std::enable_if<rexy::detail::is_string<Left>::value && std::is_rvalue_reference<Left&&>::value,void>::type* = nullptr>
constexpr auto operator+(Left&& left, const char* right){
return rexy::string_cat_expr<typename std::remove_reference<Left>::type,rexy::static_string>(std::move(left), rexy::static_string(right));
}
template<class Left, typename std::enable_if<rexy::detail::is_string<Left>::value && !std::is_rvalue_reference<Left&&>::value,void>::type* = nullptr>
constexpr auto operator+(Left&& left, const char* right){
return rexy::string_cat_expr<decltype(std::forward<Left>(left)),rexy::static_string>(std::forward<Left>(left), rexy::static_string(right));
}
template<class Left,
class Right,
typename std::enable_if<
rexy::detail::is_string<Left>::value &&
rexy::detail::is_string<Right>::value &&
std::is_rvalue_reference<Left&&>::value &&
std::is_rvalue_reference<Right&&>::value,
void>::type* = nullptr>
constexpr auto operator+(Left&& l, Right&& r){
return rexy::string_cat_expr<typename std::remove_reference<Left>::type,typename std::remove_reference<Right>::type>(std::move(l), std::move(r));
}
template<class Left,
class Right,
typename std::enable_if<
rexy::detail::is_string<Left>::value &&
rexy::detail::is_string<Right>::value &&
!std::is_rvalue_reference<Left&&>::value &&
!std::is_rvalue_reference<Right&&>::value,
void>::type* = nullptr>
constexpr auto operator+(Left&& l, Right&& r){
return rexy::string_cat_expr<decltype(std::forward<Left>(l)),decltype(std::forward<Right>(r))>(std::forward<Left>(l), std::forward<Right>(r));
}
template<class Left,
class Right,
typename std::enable_if<
rexy::detail::is_string<Left>::value &&
rexy::detail::is_string<Right>::value &&
std::is_rvalue_reference<Left&&>::value &&
!std::is_rvalue_reference<Right&&>::value,
void>::type* = nullptr>
constexpr auto operator+(Left&& l, Right&& r){
return rexy::string_cat_expr<typename std::remove_reference<Left>::type,decltype(std::forward<Right>(r))>(std::move(l), std::forward<Right>(r));
}
template<class Left,
class Right,
typename std::enable_if<
rexy::detail::is_string<Left>::value &&
rexy::detail::is_string<Right>::value &&
!std::is_rvalue_reference<Left&&>::value &&
std::is_rvalue_reference<Right&&>::value,
void>::type* = nullptr>
constexpr auto operator+(Left&& l, Right&& r){
return rexy::string_cat_expr<decltype(std::forward<Left>(l)),typename std::remove_reference<Right>::type>(std::forward<Left>(l), std::move(r));
}
template<class Left, class Right, typename std::enable_if<rexy::detail::is_string<Left>::value&&rexy::detail::is_string<Right>::value,void>::type* = nullptr>
decltype(auto) operator+=(Left& l, Right&& r){
return l = (l + std::forward<Right>(r));
}
template<class Left, typename std::enable_if<rexy::detail::is_string<Left>::value,void>::type* = nullptr>
decltype(auto) operator+=(Left& l, const char* r){
return l = (l + r);
}
#ifdef REXY_BINARY_HPP
#include <rexy/detail/binary_string_conv.hpp>

View File

@ -26,17 +26,28 @@
#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;
}
}
template<class Allocator>
constexpr string_intermediary<Allocator>::string_intermediary(void){}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(char* data, size_t len):
string_base(data, len){}
template<class Allocator>
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){}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(char* data, size_t len, size_t cap):
constexpr string_intermediary<Allocator>::string_intermediary(char* data, size_t len, size_t cap):
string_base(data, len, cap){}
template<class Allocator>
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):
string_base(data.value(), len, cap){}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(const char* data, size_t len):
@ -78,8 +89,8 @@ namespace rexy{
string_intermediary<Allocator>::string_intermediary(const string_intermediary& b):
string_base(reinterpret_cast<char*>(b.m_length ? Allocator::copy(b.m_data, b.m_length+1) : nullptr), b.m_length, b.m_cap){}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(string_intermediary&& s):
string_base(std::exchange(s.m_data, nullptr), s.m_length, s.m_cap){}
constexpr string_intermediary<Allocator>::string_intermediary(string_intermediary&& s):
string_base(cx_exchange(s.m_data, nullptr), s.m_length, s.m_cap){}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(const string_base& b):
@ -204,8 +215,8 @@ namespace rexy{
m_r(std::forward<U>(r)){}
template<class Left, class Right>
constexpr string_cat_expr<Left,Right>::string_cat_expr(const string_cat_expr& s):
m_l(std::forward<Left>(s.m_l)),
m_r(std::forward<Right>(s.m_r)){}
m_l(s.m_l),
m_r(s.m_r){}
template<class Left, class Right>
constexpr string_cat_expr<Left,Right>::string_cat_expr(string_cat_expr&& s):
m_l(std::forward<Left>(s.m_l)),