Short answer: Keep using a cast or toStr(), or write your own operator<< function. (I would prefer l1.toStr() to (string)l1.)
Long answer:
This might work if the Standard Library had a function
std::ostream& operator<<( std::ostream&, std::string const& );
Which it almost does, but not technically. Both ostream and string are really typedefs of template instantiations. And there's a template function for inserting one into the other.
// This is somewhat simplified. For the real definitions, see the Standard
// and/or your complying implementation's headers.
namespace std {
typedef basic_string<char> string;
typedef basic_ostream<char> ostream;
template <typename CharT>
basic_ostream<CharT>& operator<<(
basic_ostream<CharT>&,
basic_string<CharT> const&);
}
So when you use cout << str where the type of str is std::string, it can figure out to use that template function, with CharT = char.
But C++ doesn't allow you to have the compiler figure out both an implicit type conversion (Literal to string) and deduce template function template parameters (CharT = char) on the same call.