zstring: Fix conversion for string references

Change-Id: I0c89df2e53dc04f058c409624bb2383bc5952b3c
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/stdplus/zstring.hpp b/include/stdplus/zstring.hpp
index 28a3494..ab1e524 100644
--- a/include/stdplus/zstring.hpp
+++ b/include/stdplus/zstring.hpp
@@ -32,6 +32,17 @@
     return str.find('\0') == str.npos;
 }
 
+template <typename T, typename CharT, typename Traits>
+struct same_string : std::false_type
+{
+};
+
+template <typename CharT, typename Traits, typename Allocator>
+struct same_string<std::basic_string<CharT, Traits, Allocator>, CharT, Traits>
+    : std::true_type
+{
+};
+
 } // namespace detail
 
 /**
@@ -56,9 +67,7 @@
     using const_reference = const value_type&;
     using size_type = std::size_t;
 
-    template <typename T, size_type N,
-              std::enable_if_t<std::is_same_v<decay_t, std::remove_cvref_t<T>>,
-                               bool> = true>
+    template <typename T, size_type N>
     constexpr basic_zstring(T (&str)[N])
 #ifdef NDEBUG
         noexcept
@@ -78,12 +87,10 @@
     {
     }
     template <typename T,
-              std::enable_if_t<
-                  std::is_same_v<std::basic_string<decay_t, Traits,
-                                                   typename T::allocator_type>,
-                                 std::remove_cvref_t<T>>,
-                  bool> = true>
-    constexpr basic_zstring(T& str)
+              std::enable_if_t<detail::same_string<std::remove_cvref_t<T>,
+                                                   decay_t, Traits>::value,
+                               bool> = true>
+    constexpr basic_zstring(T&& str)
 #ifdef NDEBUG
         noexcept
 #endif
diff --git a/include/stdplus/zstring_view.hpp b/include/stdplus/zstring_view.hpp
index c97364c..a88edf8 100644
--- a/include/stdplus/zstring_view.hpp
+++ b/include/stdplus/zstring_view.hpp
@@ -73,10 +73,7 @@
 
     static constexpr size_type npos = string_view_base::npos;
 
-    template <
-        typename T, size_type N,
-        std::enable_if_t<std::is_same_v<value_type, std::remove_cvref_t<T>>,
-                         bool> = true>
+    template <typename T, size_type N>
     constexpr basic_zstring_view(T (&str)[N])
 #ifdef NDEBUG
         noexcept
@@ -96,12 +93,9 @@
     {
     }
     template <typename T,
-              std::enable_if_t<
-                  std::is_same_v<std::basic_string<value_type, Traits,
-                                                   typename T::allocator_type>,
-                                 std::remove_cvref_t<T>>,
-                  bool> = true>
-    constexpr basic_zstring_view(T& str)
+              std::enable_if_t<detail::same_string<T, CharT, Traits>::value,
+                               bool> = true>
+    constexpr basic_zstring_view(const T& str)
 #ifdef NDEBUG
         noexcept
 #endif
diff --git a/test/zstring.cpp b/test/zstring.cpp
index 07ea1f1..70f4c88 100644
--- a/test/zstring.cpp
+++ b/test/zstring.cpp
@@ -32,7 +32,14 @@
     EXPECT_EQ("c", zstring(as));
     EXPECT_EQ("c", const_zstring(as));
 
+    auto str2 = "d"s;
+    auto zs = zstring(str2);
+    EXPECT_EQ(str2, zs);
+
     std::cerr << const_zstring(as);
+
+    auto from_str = [&](const_zstring cs) { EXPECT_EQ(cs, "ac"); };
+    from_str("ac"s);
 }
 
 TEST(Zstring, NoTypeCoercion)
diff --git a/test/zstring_view.cpp b/test/zstring_view.cpp
index 8ed2f63..84b7cb8 100644
--- a/test/zstring_view.cpp
+++ b/test/zstring_view.cpp
@@ -12,6 +12,14 @@
 using std::literals::string_view_literals::operator""sv;
 using zstring_view_literals::operator""_zsv;
 
+TEST(ZstringView, IsString)
+{
+    EXPECT_TRUE((
+        detail::same_string<std::string, char, std::char_traits<char>>::value));
+    EXPECT_FALSE((detail::same_string<std::string_view, char,
+                                      std::char_traits<char>>::value));
+}
+
 TEST(ZstringView, Basic)
 {
     auto s1 = zstring_view("ac");
@@ -48,6 +56,9 @@
     std::set<zstring_view> set{s2, s2};
     EXPECT_EQ(0, set.count("ac"));
     EXPECT_EQ(1, set.count("b"));
+
+    auto from_str = [&](zstring_view cs) { EXPECT_EQ(cs, "ac"); };
+    from_str("ac"s);
 }
 
 TEST(ZstringView, ConstructError)