Since others already answered the question (I think), I'll just add a few lines of personal experience:
Using operator overloads is cool. Using template classes is cool. Using polymorphism is waaaaaay cool. However, cooler doesn't make your code better; nor does shorter. There's a reason why you have string.operator+ but not queue.operator+. Operators are meant ONLY for times when you're doing something related to an operator. Adding stuff to a buffer isn't one of them. I'll give you an example. Compare this:
Stack b;
int i;
while ((i = --b) > 0)
b--;
b += i * 2;
to this:
Stack b;
int i;
while ((i = b.Peek()) > 0)
b.Pop();
b.Push(i * 2);
See the difference? Sure, it's cooler to override some operators and write code that no one can read, but code (at least useful code) isn't meant to be cool. It's meant to work, to be reusable, to be readable, etc. C++ is a very dangerous language in that it allows you to do virtually anything, and lets you get away with it. If you're not careful what you do, you might end up knee-deep in trouble, trying to get something to work that would have worked so much better had you just written it some other way. I've been there. Don't make the same mistake.