diff options
author | Brad King <brad.king@kitware.com> | 2018-10-01 19:45:02 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2018-12-12 13:10:15 (GMT) |
commit | 80802a002c16249e99c24f62adb8ffbe006b97e0 (patch) | |
tree | 880bb7d6cc6493ffc8eb337644d3d5152e01498c /Source/cmString.hxx | |
parent | ff69763ca08fbd3a9831ec0c8adb32a7111b1a46 (diff) | |
download | CMake-80802a002c16249e99c24f62adb8ffbe006b97e0.zip CMake-80802a002c16249e99c24f62adb8ffbe006b97e0.tar.gz CMake-80802a002c16249e99c24f62adb8ffbe006b97e0.tar.bz2 |
String: Add support for concatenation by operator+
Use expression templates to collect the entire expression and
pre-allocate a string with the final length before concatenating
the pieces.
Diffstat (limited to 'Source/cmString.hxx')
-rw-r--r-- | Source/cmString.hxx | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/Source/cmString.hxx b/Source/cmString.hxx index 833234c..ddafd56 100644 --- a/Source/cmString.hxx +++ b/Source/cmString.hxx @@ -662,6 +662,107 @@ operator>=(L&& l, R&& r) std::ostream& operator<<(std::ostream& os, String const& s); std::string& operator+=(std::string& self, String const& s); +template <typename L, typename R> +struct StringOpPlus +{ + L l; + R r; +#if defined(__SUNPRO_CC) + StringOpPlus(L in_l, R in_r) + : l(in_l) + , r(in_r) + { + } +#endif + operator std::string() const; + std::string::size_type size() const { return l.size() + r.size(); } +}; + +template <typename T> +struct StringAdd +{ + static const bool value = AsStringView<T>::value; + typedef string_view temp_type; + template <typename S> + static temp_type temp(S&& s) + { + return AsStringView<T>::view(std::forward<S>(s)); + } +}; + +template <typename L, typename R> +struct StringAdd<StringOpPlus<L, R>> : std::true_type +{ + typedef StringOpPlus<L, R> const& temp_type; + static temp_type temp(temp_type s) { return s; } +}; + +template <typename L, typename R> +StringOpPlus<L, R>::operator std::string() const +{ + std::string s; + s.reserve(size()); + s += *this; + return s; +} + +template <typename L, typename R> +std::string& operator+=(std::string& s, StringOpPlus<L, R> const& a) +{ + s.reserve(s.size() + a.size()); + s += a.l; + s += a.r; + return s; +} + +template <typename L, typename R> +String& operator+=(String& s, StringOpPlus<L, R> const& a) +{ + std::string r; + r.reserve(s.size() + a.size()); + r.assign(s.data(), s.size()); + r += a.l; + r += a.r; + s = std::move(r); + return s; +} + +template <typename L, typename R> +std::ostream& operator<<(std::ostream& os, StringOpPlus<L, R> const& a) +{ + return os << a.l << a.r; +} + +template <typename L, typename R> +struct IntoString<StringOpPlus<L, R>> : std::true_type +{ + static std::string into_string(StringOpPlus<L, R> const& a) { return a; } +}; + +template <typename L, typename R> +typename std::enable_if<StringAdd<L>::value && StringAdd<R>::value, + StringOpPlus<typename StringAdd<L>::temp_type, + typename StringAdd<R>::temp_type>>::type +operator+(L&& l, R&& r) +{ + return { StringAdd<L>::temp(std::forward<L>(l)), + StringAdd<R>::temp(std::forward<R>(r)) }; +} + +template <typename LL, typename LR, typename R> +typename std::enable_if<AsStringView<R>::value, bool>::type operator==( + StringOpPlus<LL, LR> const& l, R&& r) +{ + return std::string(l) == AsStringView<R>::view(std::forward<R>(r)); +} + +template <typename L, typename RL, typename RR> +typename std::enable_if<AsStringView<L>::value, bool>::type operator==( + L&& l, StringOpPlus<RL, RR> const& r) +{ + return AsStringView<L>::view(std::forward<L>(l)) == std::string(r); +} + } // namespace cm namespace std { |