net/addr/subnet: Simplify using concepts

Change-Id: I013239f07781d18067f612a37f7c40b16609c6d6
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/stdplus/net/addr/subnet.hpp b/include/stdplus/net/addr/subnet.hpp
index 45d3cbf..05464e6 100644
--- a/include/stdplus/net/addr/subnet.hpp
+++ b/include/stdplus/net/addr/subnet.hpp
@@ -146,6 +146,23 @@
 using Subnet4 = detail::Subnet46<In4Addr, std::uint8_t>;
 using Subnet6 = detail::Subnet46<In6Addr, std::uint8_t>;
 
+class SubnetAny;
+
+template <typename T>
+struct IsSubnet : std::false_type
+{};
+
+template <typename Addr, typename Pfx>
+struct IsSubnet<detail::Subnet46<Addr, Pfx>> : std::true_type
+{};
+
+template <>
+struct IsSubnet<SubnetAny> : std::true_type
+{};
+
+template <typename T>
+concept Subnet = IsSubnet<T>::value;
+
 class SubnetAny
 {
   public:
@@ -172,9 +189,8 @@
         }
     }
 
-    template <typename T, typename S>
-    constexpr SubnetAny(detail::Subnet46<T, S> o) noexcept :
-        addr(o.getAddr()), pfx(o.getPfx())
+    template <Subnet T>
+    constexpr SubnetAny(T o) noexcept : addr(o.getAddr()), pfx(o.getPfx())
     {}
 
     constexpr auto getAddr() const noexcept
@@ -187,15 +203,11 @@
         return pfx;
     }
 
-    template <typename T, typename S>
-    constexpr bool operator==(detail::Subnet46<T, S> rhs) const noexcept
+    template <Subnet T>
+    constexpr bool operator==(T rhs) const noexcept
     {
         return addr == rhs.getAddr() && pfx == rhs.getPfx();
     }
-    constexpr bool operator==(SubnetAny rhs) const noexcept
-    {
-        return addr == rhs.addr && pfx == rhs.pfx;
-    }
 
     constexpr InAnyAddr network() const noexcept
     {
@@ -224,90 +236,51 @@
     }
 };
 
-namespace detail
-{
-
-template <typename Subnet>
-struct SubnetFromStr
+template <Subnet Sub>
+struct FromStr<Sub>
 {
     template <typename CharT>
-    constexpr Subnet operator()(std::basic_string_view<CharT> sv) const
+    constexpr Sub operator()(std::basic_string_view<CharT> sv) const
     {
         const auto pos = sv.rfind('/');
         if (pos == sv.npos)
         {
             throw std::invalid_argument("Invalid subnet");
         }
-        return {FromStr<typename Subnet::Addr>{}(sv.substr(0, pos)),
-                StrToInt<10, typename Subnet::Pfx>{}(sv.substr(pos + 1))};
+        return {FromStr<typename Sub::Addr>{}(sv.substr(0, pos)),
+                StrToInt<10, typename Sub::Pfx>{}(sv.substr(pos + 1))};
     }
 };
 
-template <typename Subnet>
-struct SubnetToStr
+template <Subnet Sub>
+struct ToStr<Sub>
 {
-    using type = Subnet;
-    using ToDec = IntToStr<10, typename Subnet::Pfx>;
+    using type = Sub;
+    using ToDec = IntToStr<10, typename Sub::Pfx>;
     // Addr + sep + 3 prefix chars
     static constexpr std::size_t buf_size =
-        ToStr<typename Subnet::Addr>::buf_size + 1 + ToDec::buf_size;
+        ToStr<typename Sub::Addr>::buf_size + 1 + ToDec::buf_size;
 
     template <typename CharT>
-    constexpr CharT* operator()(CharT* buf, Subnet v) const noexcept
+    constexpr CharT* operator()(CharT* buf, Sub v) const noexcept
     {
-        buf = ToStr<typename Subnet::Addr>{}(buf, v.getAddr());
+        buf = ToStr<typename Sub::Addr>{}(buf, v.getAddr());
         (buf++)[0] = '/';
         return ToDec{}(buf, v.getPfx());
     }
 };
 
-template <typename Subnet>
-struct SubnetHash
+} // namespace stdplus
+
+template <stdplus::Subnet Sub, typename CharT>
+struct fmt::formatter<Sub, CharT> : stdplus::Format<stdplus::ToStr<Sub>, CharT>
+{};
+
+template <stdplus::Subnet Sub>
+struct std::hash<Sub>
 {
-    constexpr std::size_t operator()(Subnet addr) const noexcept
+    constexpr std::size_t operator()(Sub addr) const noexcept
     {
         return stdplus::hashMulti(addr.getAddr(), addr.getPfx());
     }
 };
-
-} // namespace detail
-
-template <typename Addr, typename Pfx>
-struct FromStr<detail::Subnet46<Addr, Pfx>> :
-    detail::SubnetFromStr<detail::Subnet46<Addr, Pfx>>
-{};
-
-template <>
-struct FromStr<SubnetAny> : detail::SubnetFromStr<SubnetAny>
-{};
-
-template <typename Addr, typename Pfx>
-struct ToStr<detail::Subnet46<Addr, Pfx>> :
-    detail::SubnetToStr<detail::Subnet46<Addr, Pfx>>
-{};
-
-template <>
-struct ToStr<SubnetAny> : detail::SubnetToStr<SubnetAny>
-{};
-
-} // namespace stdplus
-
-template <typename Addr, typename Pfx, typename CharT>
-struct fmt::formatter<stdplus::detail::Subnet46<Addr, Pfx>, CharT> :
-    stdplus::Format<stdplus::ToStr<stdplus::detail::Subnet46<Addr, Pfx>>, CharT>
-{};
-
-template <typename CharT>
-struct fmt::formatter<stdplus::SubnetAny, CharT> :
-    stdplus::Format<stdplus::ToStr<stdplus::SubnetAny>, CharT>
-{};
-
-template <typename Addr, typename Pfx>
-struct std::hash<stdplus::detail::Subnet46<Addr, Pfx>> :
-    stdplus::detail::SubnetHash<stdplus::detail::Subnet46<Addr, Pfx>>
-{};
-
-template <>
-struct std::hash<stdplus::SubnetAny> :
-    stdplus::detail::SubnetHash<stdplus::SubnetAny>
-{};
diff --git a/src/net/addr/subnet.cpp b/src/net/addr/subnet.cpp
index 47f028f..90fb702 100644
--- a/src/net/addr/subnet.cpp
+++ b/src/net/addr/subnet.cpp
@@ -4,7 +4,10 @@
 
 #include <stdexcept>
 
-namespace stdplus::detail
+namespace stdplus
+{
+
+namespace detail
 {
 
 void invalidSubnetPfx(std::size_t pfx)
@@ -15,13 +18,14 @@
 template class Subnet46<In4Addr, uint8_t>;
 template class Subnet46<In6Addr, uint8_t>;
 
-template Subnet4 SubnetFromStr<Subnet4>::operator()(std::string_view) const;
-template Subnet6 SubnetFromStr<Subnet6>::operator()(std::string_view) const;
-template SubnetAny SubnetFromStr<SubnetAny>::operator()(std::string_view) const;
+} // namespace detail
 
-template char* SubnetToStr<Subnet4>::operator()(char*, Subnet4) const noexcept;
-template char* SubnetToStr<Subnet6>::operator()(char*, Subnet6) const noexcept;
-template char* SubnetToStr<SubnetAny>::operator()(char*,
-                                                  SubnetAny) const noexcept;
+template Subnet4 FromStr<Subnet4>::operator()(std::string_view) const;
+template Subnet6 FromStr<Subnet6>::operator()(std::string_view) const;
+template SubnetAny FromStr<SubnetAny>::operator()(std::string_view) const;
 
-} // namespace stdplus::detail
+template char* ToStr<Subnet4>::operator()(char*, Subnet4) const noexcept;
+template char* ToStr<Subnet6>::operator()(char*, Subnet6) const noexcept;
+template char* ToStr<SubnetAny>::operator()(char*, SubnetAny) const noexcept;
+
+} // namespace stdplus