net/addr/ip: Fix operator== abiguity

Change-Id: Ie7bd7dee85e1e564c1b1a873d9fb0cb9d4ee050f
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/stdplus/net/addr/ip.hpp b/include/stdplus/net/addr/ip.hpp
index c35fb44..d03f76f 100644
--- a/include/stdplus/net/addr/ip.hpp
+++ b/include/stdplus/net/addr/ip.hpp
@@ -379,6 +379,16 @@
 using InAnyAddrV = std::variant<In4Addr, In6Addr>;
 }
 
+struct InAnyAddr;
+
+template <typename Addr>
+concept InAddr = std::same_as<Addr, In4Addr> || std::same_as<Addr, In6Addr> ||
+                 std::same_as<Addr, InAnyAddr>;
+
+template <typename Addr>
+concept InAddrLike = InAddr<Addr> || std::same_as<Addr, in_addr> ||
+                     std::same_as<Addr, in6_addr>;
+
 struct InAnyAddr : detail::InAnyAddrV
 {
     constexpr InAnyAddr(in_addr a) noexcept : detail::InAnyAddrV(In4Addr{a}) {}
@@ -386,7 +396,8 @@
     constexpr InAnyAddr(in6_addr a) noexcept : detail::InAnyAddrV(In6Addr{a}) {}
     constexpr InAnyAddr(In6Addr a) noexcept : detail::InAnyAddrV(a) {}
 
-    constexpr bool operator==(auto rhs) const noexcept
+    template <InAddrLike T>
+    constexpr bool operator==(T rhs) const noexcept
     {
         return variantEqFuzzy(*this, rhs);
     }
@@ -421,10 +432,6 @@
     }
 };
 
-template <typename Addr>
-concept InAddr = std::same_as<Addr, In4Addr> || std::same_as<Addr, In6Addr> ||
-                 std::same_as<Addr, InAnyAddr>;
-
 namespace detail
 {
 
diff --git a/test/net/addr/ip.cpp b/test/net/addr/ip.cpp
index 2133d3e..2ce2580 100644
--- a/test/net/addr/ip.cpp
+++ b/test/net/addr/ip.cpp
@@ -221,6 +221,8 @@
     EXPECT_EQ("ff::", tsh(In6Addr{0, 0xff}));
 
     EXPECT_EQ("a ff00:: b", fmt::format("a {} b", InAnyAddr{In6Addr{0xff}}));
+    EXPECT_NE("0.0.0.0"_ip, std::optional<InAnyAddr>());
+    EXPECT_EQ("0.0.0.0"_ip, std::optional<InAnyAddr>(In4Addr{}));
 }
 
 TEST(Loopback, In4Addr)