https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89793
--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Harald van Dijk from comment #1) > Your StringType provides a conversion operator to HTTPResponse, which > indirectly has std::allocator<char> as a private base class. Overload > resolution happens before access checks, so the fact that it is a private > base class does not prevent the construction of std::string from being > ambiguous: the conversion to HTTPResponse could be used followed by the > construction of a new std::string using the HTTPResponse as the allocator. Right, the code is equivalent to this: #include <string> struct NotString : std::allocator<char> { }; struct String { operator std::string() const; operator NotString() const; }; struct Message { template<typename T> Message(T&& t) : s{t} { } std::string s; }; int main() { String s; Message m(s); } > This appears to work the same way in GCC 8 as it does in GCC 7, although it > is possible that for whatever reason, the GCC 7 version ends up not > including std::allocator<char> as a base class. There was a change in overload resolution between GCC 7 and 8.