Jelajahi Sumber

cm::String: enhance compatibility with STL

Marc Chevrier 5 tahun lalu
induk
melakukan
8f839d02e3

+ 1 - 1
Source/cmGeneratorExpressionNode.cxx

@@ -14,6 +14,7 @@
 #include <utility>
 
 #include <cm/iterator>
+#include <cm/string_view>
 
 #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"

+ 0 - 1
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"

+ 164 - 48
Source/cmString.hxx

@@ -87,18 +87,6 @@ struct IntoString<std::string> : std::true_type
   static std::string into_string(std::string s) { return s; }
 };
 
-template <>
-struct IntoString<string_view> : std::true_type
-{
-  static std::string into_string(string_view s) { return std::string(s); }
-};
-
-template <>
-struct IntoString<static_string_view> : std::true_type
-{
-  static string_view into_string(static_string_view s) { return s; }
-};
-
 template <>
 struct IntoString<char> : std::true_type
 {
@@ -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<char> 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 T>
   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 L, typename R>
-typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
-                        bool>::type
-operator==(L&& l, R&& r)
+/**
+ * Trait for comparable types.
+ */
+template <typename T>
+struct IsComparable : std::false_type
+{
+};
+
+template <typename T>
+struct IsComparable<T&> : IsComparable<T>
+{
+};
+
+template <typename T>
+struct IsComparable<T const> : IsComparable<T>
+{
+};
+
+template <typename T>
+struct IsComparable<T const*> : IsComparable<T*>
+{
+};
+
+template <typename T, std::string::size_type N>
+struct IsComparable<T const[N]> : IsComparable<T[N]>
+{
+};
+
+template <>
+struct IsComparable<char*> : std::true_type
 {
-  return (AsStringView<L>::view(std::forward<L>(l)) ==
-          AsStringView<R>::view(std::forward<R>(r)));
+};
+
+template <std::string::size_type N>
+struct IsComparable<char[N]> : std::true_type
+{
+};
+
+template <>
+struct IsComparable<std::string> : std::true_type
+{
+};
+
+template <>
+struct IsComparable<char> : std::true_type
+{
+};
+
+/** comparison operators */
+inline bool operator==(const String& l, const String& r)
+{
+  return l.view() == r.view();
+}
+template <typename L>
+typename std::enable_if<IsComparable<L>::value, bool>::type operator==(
+  L&& l, const String& r)
+{
+  return AsStringView<L>::view(std::forward<L>(l)) == r.view();
+}
+template <typename R>
+typename std::enable_if<IsComparable<R>::value, bool>::type operator==(
+  const String& l, R&& r)
+{
+  return l.view() == AsStringView<R>::view(std::forward<R>(r));
 }
 
-template <typename L, typename R>
-typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
-                        bool>::type
-operator!=(L&& l, R&& r)
+inline bool operator!=(const String& l, const String& r)
+{
+  return l.view() != r.view();
+}
+template <typename L>
+typename std::enable_if<IsComparable<L>::value, bool>::type operator!=(
+  L&& l, const String& r)
 {
-  return (AsStringView<L>::view(std::forward<L>(l)) !=
-          AsStringView<R>::view(std::forward<R>(r)));
+  return AsStringView<L>::view(std::forward<L>(l)) != r.view();
+}
+template <typename R>
+typename std::enable_if<IsComparable<R>::value, bool>::type operator!=(
+  const String& l, R&& r)
+{
+  return l.view() != AsStringView<R>::view(std::forward<R>(r));
 }
 
-template <typename L, typename R>
-typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
-                        bool>::type
-operator<(L&& l, R&& r)
+inline bool operator<(const String& l, const String& r)
 {
-  return (AsStringView<L>::view(std::forward<L>(l)) <
-          AsStringView<R>::view(std::forward<R>(r)));
+  return l.view() < r.view();
+}
+template <typename L>
+typename std::enable_if<IsComparable<L>::value, bool>::type operator<(
+  L&& l, const String& r)
+{
+  return AsStringView<L>::view(std::forward<L>(l)) < r.view();
+}
+template <typename R>
+typename std::enable_if<IsComparable<R>::value, bool>::type operator<(
+  const String& l, R&& r)
+{
+  return l.view() < AsStringView<R>::view(std::forward<R>(r));
 }
 
-template <typename L, typename R>
-typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
-                        bool>::type
-operator<=(L&& l, R&& r)
+inline bool operator<=(const String& l, const String& r)
+{
+  return l.view() <= r.view();
+}
+template <typename L>
+typename std::enable_if<IsComparable<L>::value, bool>::type operator<=(
+  L&& l, const String& r)
+{
+  return AsStringView<L>::view(std::forward<L>(l)) <= r.view();
+}
+template <typename R>
+typename std::enable_if<IsComparable<R>::value, bool>::type operator<=(
+  const String& l, R&& r)
 {
-  return (AsStringView<L>::view(std::forward<L>(l)) <=
-          AsStringView<R>::view(std::forward<R>(r)));
+  return l.view() <= AsStringView<R>::view(std::forward<R>(r));
 }
 
-template <typename L, typename R>
-typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
-                        bool>::type
-operator>(L&& l, R&& r)
+inline bool operator>(const String& l, const String& r)
+{
+  return l.view() > r.view();
+}
+template <typename L>
+typename std::enable_if<IsComparable<L>::value, bool>::type operator>(
+  L&& l, const String& r)
+{
+  return AsStringView<L>::view(std::forward<L>(l)) > r.view();
+}
+template <typename R>
+typename std::enable_if<IsComparable<R>::value, bool>::type operator>(
+  const String& l, R&& r)
 {
-  return (AsStringView<L>::view(std::forward<L>(l)) >
-          AsStringView<R>::view(std::forward<R>(r)));
+  return l.view() > AsStringView<R>::view(std::forward<R>(r));
 }
 
-template <typename L, typename R>
-typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
-                        bool>::type
-operator>=(L&& l, R&& r)
+inline bool operator>=(const String& l, const String& r)
+{
+  return l.view() >= r.view();
+}
+template <typename L>
+typename std::enable_if<IsComparable<L>::value, bool>::type operator>=(
+  L&& l, const String& r)
+{
+  return AsStringView<L>::view(std::forward<L>(l)) >= r.view();
+}
+template <typename R>
+typename std::enable_if<IsComparable<R>::value, bool>::type operator>=(
+  const String& l, R&& r)
 {
-  return (AsStringView<L>::view(std::forward<L>(l)) >=
-          AsStringView<R>::view(std::forward<R>(r)));
+  return l.view() >= AsStringView<R>::view(std::forward<R>(r));
 }
 
 std::ostream& operator<<(std::ostream& os, String const& s);

+ 5 - 5
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();