I am struggling to understand why the following code does not allow an implicit conversion to occur.
#include
using namespace std;
struct HasConv
The one you want to call is a function template:
template
bool operator<(std::basic_string const& lhs,
std::basic_string const& rhs);
Deduction fails for the second argument because a HasConversionToString is not a std::basic_string - template argument deduction doesn't look through implicit conversions. As a result, that function template is removed from overload resolution.
std::experimental::basic_string_view has a similar problem, which was solved by a "sufficient additional overloads" rule (the library must add enough overloads so that comparison between a basic_string_view and something convertible to one works).
You don't really want such a thing for basic_string, though - having < possibly silently causing a trip to the heap is not really a good idea.