TextView - add generic constructor.
diff --git a/code/include/swoc/TextView.h b/code/include/swoc/TextView.h
index 2481cda..3b74e0e 100644
--- a/code/include/swoc/TextView.h
+++ b/code/include/swoc/TextView.h
@@ -79,6 +79,22 @@
    */
   constexpr TextView(char const *first, char const *last) noexcept;
 
+  /** Construct from any character container following STL standards.
+   *
+   * @tparam C Container type.
+   * @param c container
+   *
+   * The container type must have the methods @c data and @c size which must return values convertible
+   * to @c char @c const @c * and @c size_t respectively.
+   */
+  template < typename C
+    , typename = typename std::enable_if<
+        std::is_convertible_v<decltype(std::declval<C>().data()), char const*> &&
+        std::is_convertible_v<decltype(std::declval<C>().size()), size_t>
+        , void
+      >::type
+  > constexpr TextView(C const& c);
+
   /** Construct from literal string or array.
 
       All elements of the array are included in the view unless the last element is nul, in which case it is elided.
@@ -164,6 +180,24 @@
   /// Explicitly set the view from a @c std::string
   self_type &assign(std::string const &s);
 
+  /** Assogm from any character container following STL standards.
+   *
+   * @tparam C Container type.
+   * @param c container
+   *
+   * The container type must have the methods @c data and @c size which must return values convertible
+   * to @c char @c const @c * and @c size_t respectively.
+   */
+  template < typename C
+            , typename = typename std::enable_if<
+                std::is_convertible_v<decltype(std::declval<C>().data()), char const*> &&
+                std::is_convertible_v<decltype(std::declval<C>().size()), size_t>
+                , void
+              >::type
+            > constexpr self_type & assign(C const& c) {
+    return this->assign(c.data(), c.size());
+  }
+
   /** Dereference operator.
 
       @note This allows the view to be used as if it were a character iterator to a null terminated
@@ -923,6 +957,7 @@
 inline TextView::TextView(std::string const &str) noexcept : super_type(str) {}
 inline constexpr TextView::TextView(super_type const &that) noexcept : super_type(that) {}
 template <size_t N> constexpr TextView::TextView(const char (&s)[N]) noexcept : super_type(s, s[N - 1] ? N : N - 1) {}
+template <typename C, typename> constexpr TextView::TextView(C const &c) : super_type(c.data(), c.size()) {}
 
 inline void
 TextView::init_delimiter_set(std::string_view const &delimiters, std::bitset<256> &set) {
diff --git a/doc/code/TextView.en.rst b/doc/code/TextView.en.rst
index 5009c62..5b8f9f8 100644
--- a/doc/code/TextView.en.rst
+++ b/doc/code/TextView.en.rst
@@ -63,11 +63,11 @@
 :code:`assign` or :code:`clear` methods.
 
 When passing |TV| as an argument, it is very debatable whether passing by value or passing by
-reference is more efficient, therefore it's not likely to matter in production code. My personal
-heuristic is whether the function will modify the value. If so, passing by value saves a copy to a
-local variable therefore it should be passed by value. If the function simply passes the |TV| on to
-other functions, then pass by constant reference. This distinction is irrelevant to the caller, the
-same code at the call site will work in either case.
+reference is more efficient. The appropriate conclusion is it's not likely to matter in production
+code. My personal heuristic is whether the function will modify the value. If so, passing by value
+saves a copy to a local variable therefore it should be passed by value. If the function simply
+passes the |TV| on to other functions, then pass by constant reference. This distinction is
+irrelevant to the caller, the same code at the call site will work in either case.
 
 As noted, |TV| is designed as a pointer style class. Therefore it has an increment operator which is
 equivalent to :code:`std::string_view::remove_prefix`. |TV| also has  a dereference operator, which
@@ -121,6 +121,11 @@
 A |TV| can be constructed from a null :code:`char const*` pointer or a straight :code:`nullptr`. This
 will construct an empty |TV| identical to one default constructed.
 
+|TV| supports a generic constructor that will accept any class that provides the :code:`data` and
+:code:`size` methods that return values convertible to :code:`char const *` and :code:`size_t`.
+This enables greater interoperability with other libraries, as any well written C++ library with
+its own string class will have these methods implemented sensibly.
+
 Searching
 ---------
 
@@ -176,7 +181,7 @@
 This is a table of the affix oriented methods, grouped by the properties of the methods. "Bounded"
 indicates whether the operation requires the target character, however specified, to be within the
 bounds of the view. A bounded method does nothing if the target character is not in the view. On
-this note, the :code:`remove_prefix` and :code:`remove_suffix` are differently implement in |TV|
+this note, the :code:`remove_prefix` and :code:`remove_suffix` are implemented differently in |TV|
 compared to :code:`std::string_view`. Rather than being undefined, the methods will clear the view
 if the size specified is larger than the contents of the view.
 
diff --git a/unit_tests/test_TextView.cc b/unit_tests/test_TextView.cc
index 6807020..8a77277 100644
--- a/unit_tests/test_TextView.cc
+++ b/unit_tests/test_TextView.cc
@@ -96,6 +96,33 @@
   REQUIRE(strcasecmp(tv, tv) == 0);
   REQUIRE(strcasecmp(tv, tv_lower) == 0);
   REQUIRE(strcasecmp(nothing, tv) != 0);
+
+  // Check generic construction from a "string like" class.
+  struct Stringy {
+    char const * data() const { return _data; }
+    size_t size() const { return _size; }
+
+    char const * _data = nullptr;
+    size_t _size;
+  };
+
+  char const * stringy_text = "Evil Dave Rulez";
+  Stringy stringy{stringy_text, strlen(stringy_text)};
+
+  // Can construct directly.
+  TextView from_stringy{stringy};
+  REQUIRE(0 == strcmp(from_stringy, stringy_text));
+
+  // Can assign directly.
+  TextView assign_stringy;
+  REQUIRE(assign_stringy.empty() == true);
+  assign_stringy.assign(stringy);
+  REQUIRE(0 == strcmp(assign_stringy, stringy_text));
+
+  // Pass as argument to TextView parameter.
+  auto stringy_f = [&](TextView txt) -> bool { return 0 == strcmp(txt, stringy_text); };
+  REQUIRE(true == stringy_f(stringy));
+  REQUIRE(false == stringy_f(tv_lower));
 }
 
 TEST_CASE("TextView Trimming", "[libswoc][TextView]")