Fix some issues with rvalue refs in string expressions

This commit is contained in:
rexy712 2019-10-28 12:40:44 -07:00
parent cf4485bab9
commit 145a77c3a6

View File

@ -145,9 +145,7 @@ namespace raii{
string_intermediary& operator=(const string_intermediary& s){
string_intermediary tmp(s);
std::swap(m_data, tmp.m_data);
m_length = tmp.m_length;
return *this;
return (*this = std::move(tmp));
}
string_intermediary& operator=(string_intermediary&& s){
std::swap(m_data, s.m_data);
@ -290,16 +288,15 @@ namespace raii{
Right m_r;
public:
template<class T, class U>
constexpr string_cat_expr(T&& l, U&& r):
constexpr string_cat_expr(Left l, Right r):
m_l(std::forward<Left>(l)),
m_r(std::forward<Right>(r)){}
constexpr string_cat_expr(const string_cat_expr& s):
m_l(s.m_l),
m_r(s.m_r){}
m_l(std::forward<Left>(s.m_l)),
m_r(std::forward<Right>(s.m_r)){}
constexpr string_cat_expr(string_cat_expr&& s):
m_l(s.m_l),
m_r(s.m_r){}
m_l(std::forward<Left>(s.m_l)),
m_r(std::forward<Right>(s.m_r)){}
constexpr size_t length(void)const{
return _llen() + _rlen();
@ -360,18 +357,69 @@ bool operator!=(Str1&& left, Str2&& right){
return !(left == right);
}
template<class Right, typename std::enable_if<raii::detail::is_string<Right>::value,void>::type* = nullptr>
template<class Right, typename std::enable_if<raii::detail::is_string<Right>::value && std::is_rvalue_reference<Right&&>::value,void>::type* = nullptr>
constexpr auto operator+(const char* left, Right&& right){
return raii::string_cat_expr<const char*,typename std::remove_reference<Right>::type>(left, std::move(right));
}
template<class Right, typename std::enable_if<raii::detail::is_string<Right>::value && !std::is_rvalue_reference<Right&&>::value,void>::type* = nullptr>
constexpr auto operator+(const char* left, Right&& right){
return raii::string_cat_expr<const char*,decltype(std::forward<Right>(right))>(left, std::forward<Right>(right));
}
template<class Left, typename std::enable_if<raii::detail::is_string<Left>::value,void>::type* = nullptr>
template<class Left, typename std::enable_if<raii::detail::is_string<Left>::value && std::is_rvalue_reference<Left&&>::value,void>::type* = nullptr>
constexpr auto operator+(Left&& left, const char* right){
return raii::string_cat_expr<typename std::remove_reference<Left>::type,const char*>(std::move(left), right);
}
template<class Left, typename std::enable_if<raii::detail::is_string<Left>::value && !std::is_rvalue_reference<Left&&>::value,void>::type* = nullptr>
constexpr auto operator+(Left&& left, const char* right){
return raii::string_cat_expr<decltype(std::forward<Left>(left)),const char*>(std::forward<Left>(left), right);
}
template<class Left, class Right, typename std::enable_if<raii::detail::is_string<Left>::value&&raii::detail::is_string<Right>::value,void>::type* = nullptr>
template<class Left,
class Right,
typename std::enable_if<
raii::detail::is_string<Left>::value &&
raii::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 raii::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<
raii::detail::is_string<Left>::value &&
raii::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 raii::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<
raii::detail::is_string<Left>::value &&
raii::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 raii::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<
raii::detail::is_string<Left>::value &&
raii::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 raii::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<raii::detail::is_string<Left>::value&&raii::detail::is_string<Right>::value,void>::type* = nullptr>
decltype(auto) operator+=(Left& l, Right&& r){
return l = (l + std::forward<Right>(r));