
I have found a couple of "undocumented features" in operators.hpp: 1) The return values from a lot of the binary operators should be declared const, so that it is not possible to assign to the temporary object that results from the operation. An example: if(!(a/b=c/d))... This statement is obviously a typo. The assignment operator= should have been a comparison operator==. With the current definition of operator/ in operators.hpp, the compiler will not recognize this as an error. Instead, the following will happen: first, the values of a/b and b/c are calculated and placed in temporary objects. Then, the result of a/b is overwritten by the result of c/d. Finally, operator! converts that to a boolean and the if statement acts on it (in other words, the statement is probably interpreted as "if(!c)..."). If, on the other hand, the return value from operator/ is declared constant, the compiler will catch the error, and probably say something like "lvalue required". Much better. 2) I think the "Named Return Value Optimization" code is a misunderstanding. The way I read the excerpts from the C++ standard quoted in the documentation (see http://www.boost.org/libs/utility/operators.htm#symmetry) is as follows: The standard places some limits on when NAMED objects may be optimized away. From this follows implicitly that UNNAMED objects may always be optimized away. Or, to quote from Scott Meyers' "More Effective C++", page 109-110: "However, the fact remains that unnamed objects have historically been easier to eliminate than named objects, so when faced with a choice between a named object and a temporary object, you may be better off using the temporary. It should never cost you more than its named collegue, and, especially with older compilers, it may cost you less". In other words: some compilers may not have Named Return Value Optimization, but most of them have (Unnamed) Return Value Optimization, which means that temporary, unnamed objects are optimized away where possible. So, I think, a better way of writing e.g. operator+ is the good old-fashioned: template <class T> inline const T operator+(const T& lhs,const T& rhs) {return T(lhs) += rhs;}; 3) When using compilers that do not support operators in namespaces (#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE), the operator templates are first placed in the global namespace, and then copied to the boost namespace. The consequence of this is that it is not possible to access the templates with a "using namespace boost;" declaration - trying to do so creates an ambiguity between the stuff in boost and the stuff in the global namespace. Also, of course, the global namespace is "polluted" with quite a lot of extra names. The solution to this problem is to declare all the templates inside a "pseudo-namespace" struct in the global namespace - this also makes it easier to import the templates into boost, as even the Borland compiler now recognizes a "using" declaration. I have uploaded a new version of "operators.hpp" with fixes for above-mentioned problems to the sandbox vault. It has been tested with "rational.hpp" on the Borland 5.5 compiler and the Microsoft version 13.10.3077 compiler (the one that comes with the free Visual Toolkit 2003, and also (I think) with Visual C++ 7.1). I hope that some of you have time to test my new version with other programs and compilers. --- Søren