From 8f839d02e3c5b6468cbc4120f1829621a59997d8 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Fri, 24 Jan 2020 12:16:58 +0100 Subject: cm::String: enhance compatibility with STL --- Source/cmGeneratorExpressionNode.cxx | 2 +- Source/cmQtAutoGenInitializer.cxx | 1 - Source/cmString.hxx | 212 +++++++++++++++++++++++++++-------- Tests/CMakeLib/testString.cxx | 10 +- 4 files changed, 170 insertions(+), 55 deletions(-) diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 66f1c71..14478c2 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -14,6 +14,7 @@ #include #include +#include #include "cmsys/RegularExpression.hxx" #include "cmsys/String.h" @@ -37,7 +38,6 @@ #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" -#include "cmString.hxx" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index ebb522b..acd85a0 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -42,7 +42,6 @@ #include "cmSourceGroup.h" #include "cmState.h" #include "cmStateTypes.h" -#include "cmString.hxx" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" diff --git a/Source/cmString.hxx b/Source/cmString.hxx index 073f4c9..9e91986 100644 --- a/Source/cmString.hxx +++ b/Source/cmString.hxx @@ -88,18 +88,6 @@ struct IntoString : std::true_type }; template <> -struct IntoString : std::true_type -{ - static std::string into_string(string_view s) { return std::string(s); } -}; - -template <> -struct IntoString : std::true_type -{ - static string_view into_string(static_string_view s) { return s; } -}; - -template <> struct IntoString : std::true_type { static std::string into_string(char const& c) { return std::string(1, c); } @@ -239,6 +227,25 @@ public: { } + /** + * Construct via static_string_view constructor. + * explicit is required to avoid ambiguous overloaded operators (i.e ==, + * etc...) with the ones provided by string_view. + */ + explicit String(static_string_view s) + : String(s, Private()) + { + } + /** + * Construct via string_view constructor. + * explicit is required to avoid ambiguous overloaded operators (i.e ==, + * etc...) with the ones provided by string_view. + */ + explicit String(string_view s) + : String(std::string(s), Private()) + { + } + /** Construct via std::string initializer list constructor. */ String(std::initializer_list il) : String(std::string(il)) @@ -306,6 +313,17 @@ public: This shares ownership of the other string's buffer. */ String& operator=(String const&) noexcept = default; + String& operator=(static_string_view s) + { + *this = String(s); + return *this; + } + String& operator=(string_view s) + { + *this = String(s); + return *this; + } + /** Assign from any type implementing the IntoString trait. */ template typename // NOLINT(*) @@ -328,6 +346,7 @@ public: /** Return a view of the string. */ string_view view() const noexcept { return view_; } + operator string_view() const noexcept { return this->view(); } /** Return true if the instance is an empty stringn or null string. */ bool empty() const noexcept { return view_.empty(); } @@ -638,58 +657,155 @@ private: string_view view_; }; -template -typename std::enable_if::value && AsStringView::value, - bool>::type -operator==(L&& l, R&& r) +/** + * Trait for comparable types. + */ +template +struct IsComparable : std::false_type +{ +}; + +template +struct IsComparable : IsComparable +{ +}; + +template +struct IsComparable : IsComparable +{ +}; + +template +struct IsComparable : IsComparable +{ +}; + +template +struct IsComparable : IsComparable +{ +}; + +template <> +struct IsComparable : std::true_type { - return (AsStringView::view(std::forward(l)) == - AsStringView::view(std::forward(r))); +}; + +template +struct IsComparable : std::true_type +{ +}; + +template <> +struct IsComparable : std::true_type +{ +}; + +template <> +struct IsComparable : std::true_type +{ +}; + +/** comparison operators */ +inline bool operator==(const String& l, const String& r) +{ + return l.view() == r.view(); +} +template +typename std::enable_if::value, bool>::type operator==( + L&& l, const String& r) +{ + return AsStringView::view(std::forward(l)) == r.view(); +} +template +typename std::enable_if::value, bool>::type operator==( + const String& l, R&& r) +{ + return l.view() == AsStringView::view(std::forward(r)); } -template -typename std::enable_if::value && AsStringView::value, - bool>::type -operator!=(L&& l, R&& r) +inline bool operator!=(const String& l, const String& r) +{ + return l.view() != r.view(); +} +template +typename std::enable_if::value, bool>::type operator!=( + L&& l, const String& r) { - return (AsStringView::view(std::forward(l)) != - AsStringView::view(std::forward(r))); + return AsStringView::view(std::forward(l)) != r.view(); +} +template +typename std::enable_if::value, bool>::type operator!=( + const String& l, R&& r) +{ + return l.view() != AsStringView::view(std::forward(r)); } -template -typename std::enable_if::value && AsStringView::value, - bool>::type -operator<(L&& l, R&& r) +inline bool operator<(const String& l, const String& r) { - return (AsStringView::view(std::forward(l)) < - AsStringView::view(std::forward(r))); + return l.view() < r.view(); +} +template +typename std::enable_if::value, bool>::type operator<( + L&& l, const String& r) +{ + return AsStringView::view(std::forward(l)) < r.view(); +} +template +typename std::enable_if::value, bool>::type operator<( + const String& l, R&& r) +{ + return l.view() < AsStringView::view(std::forward(r)); } -template -typename std::enable_if::value && AsStringView::value, - bool>::type -operator<=(L&& l, R&& r) +inline bool operator<=(const String& l, const String& r) +{ + return l.view() <= r.view(); +} +template +typename std::enable_if::value, bool>::type operator<=( + L&& l, const String& r) +{ + return AsStringView::view(std::forward(l)) <= r.view(); +} +template +typename std::enable_if::value, bool>::type operator<=( + const String& l, R&& r) { - return (AsStringView::view(std::forward(l)) <= - AsStringView::view(std::forward(r))); + return l.view() <= AsStringView::view(std::forward(r)); } -template -typename std::enable_if::value && AsStringView::value, - bool>::type -operator>(L&& l, R&& r) +inline bool operator>(const String& l, const String& r) +{ + return l.view() > r.view(); +} +template +typename std::enable_if::value, bool>::type operator>( + L&& l, const String& r) +{ + return AsStringView::view(std::forward(l)) > r.view(); +} +template +typename std::enable_if::value, bool>::type operator>( + const String& l, R&& r) { - return (AsStringView::view(std::forward(l)) > - AsStringView::view(std::forward(r))); + return l.view() > AsStringView::view(std::forward(r)); } -template -typename std::enable_if::value && AsStringView::value, - bool>::type -operator>=(L&& l, R&& r) +inline bool operator>=(const String& l, const String& r) +{ + return l.view() >= r.view(); +} +template +typename std::enable_if::value, bool>::type operator>=( + L&& l, const String& r) +{ + return AsStringView::view(std::forward(l)) >= r.view(); +} +template +typename std::enable_if::value, bool>::type operator>=( + const String& l, R&& r) { - return (AsStringView::view(std::forward(l)) >= - AsStringView::view(std::forward(r))); + return l.view() >= AsStringView::view(std::forward(r)); } std::ostream& operator<<(std::ostream& os, String const& s); diff --git a/Tests/CMakeLib/testString.cxx b/Tests/CMakeLib/testString.cxx index d7b3200..1fd3f38 100644 --- a/Tests/CMakeLib/testString.cxx +++ b/Tests/CMakeLib/testString.cxx @@ -191,7 +191,7 @@ static bool testConstructFromView() { std::cout << "testConstructFromView()\n"; cm::string_view view = cstr; - return testFromCStr(view); + return testFromCStr(cm::String(view)); } static bool testAssignFromView() @@ -297,7 +297,7 @@ static bool testFromStaticStringView(cm::String str) static bool testConstructFromStaticStringView() { std::cout << "testConstructFromStaticStringView()\n"; - return testFromStaticStringView(staticStringView); + return testFromStaticStringView(cm::String(staticStringView)); } static bool testAssignFromStaticStringView() @@ -796,7 +796,7 @@ static bool testMethod_substr_AtEnd(cm::String str) static bool testMethod_substr_AtEndBorrowed() { std::cout << "testMethod_substr_AtEndBorrowed()\n"; - return testMethod_substr_AtEnd("abc"_s); + return testMethod_substr_AtEnd(cm::String("abc"_s)); } static bool testMethod_substr_AtEndOwned() @@ -855,7 +855,7 @@ static bool testMethod_substr_AtStart(cm::String str) static bool testMethod_substr_AtStartBorrowed() { std::cout << "testMethod_substr_AtStartBorrowed()\n"; - return testMethod_substr_AtStart("abc"_s); + return testMethod_substr_AtStart(cm::String("abc"_s)); } static bool testMethod_substr_AtStartOwned() @@ -1146,7 +1146,7 @@ static bool testAddition() static bool testStability() { std::cout << "testStability()\n"; - cm::String str = "abc"_s; + cm::String str("abc"_s); ASSERT_TRUE(!str.is_stable()); ASSERT_TRUE(str.str_if_stable() == nullptr); str.stabilize(); -- cgit v0.12