See, your operator << was never meant to output std::sets like that. There was no version of it that could take an std::ostream& on one side and an std::set<string> on the other, and return an std::ostream&. So, what gulkan did was defined such an operator, or rather, he overloaded the existing operator, making it change meanings for different types. He still uses the same << symbol, but it has a different meaning when what's on the left is an std::ostream& and what's on the right is an std::set<string>.
Line 11 declares the operator overload, which is similar in syntax and usage to a function declaration, and everything from there up to line 19 explains what it does.
Here's a template for future usage: /*returntype*/ operator /*symbol*/ (/*left-argument*/, /*right-argument*/)
Note that there are only a finite number of symbols that can be overloaded like this.