An empty line is the "smallest" of all lines, that is, it is compared less than any non-empty line.
ยง21.4.8.4 [string :: op <]:
template<class charT, class traits, class Allocator> bool operator< (const basic_string<charT,traits,Allocator>& lhs, const basic_string<charT,traits,Allocator>& rhs) noexcept;
1 Returns: lhs.compare(rhs) < 0 .
ยง21.4.7.9 [string :: compare]:
int compare(const basic_string& str) const noexcept;
1 Effects: Determines the effective length of rlen lines, compare as the smallest of size() and str.size() . The function then compares the two lines, calling traits::compare(data(), str.data(), rlen) .
2 Refunds: An excellent result if the result of the comparison is non-zero. Otherwise, returns the value specified in Table 72.
Table 72 - comparison results ()
Condition Return Value size() < str.size() < 0 size() == str.size() 0 size() > str.size() > 0
For any comparison between an empty string e and a non-empty string ne , rlen is zero, in which case traits::compare() specified to return zero * . Therefore, the result of e.compare(ne) always less than zero on table 72, and e < ne always true.
* The function of symbolic signs compare() is indicated for returning zero if "for each I from [0, n), X::eq(p[i],q[i]) true" (ยง21.2.1 [char.traits .require], table 62); when n == 0 , the range is empty and the condition remains undefined.