Flylib.com

Books Software

 
 
 

Utility Summary


Utility Summary

This chapter has demonstrated some useful utility classes that can greatly simplify our daily life. BOOST_STATIC_ASSERT asserts at compile time, which is very helpful both for testing preconditions and enforcing other requirements. For generic programming, checked_delete is extremely helpful in detecting erroneous usage, which in turn can save a lot of time reading terribly verbose error messages and studying code that seems just fine. We have also covered addressof , which is a handy tool for getting to the real address of an object, regardless of what operator& says. We also saw how enable_if and disable_if can control which functions participate in overload resolution and learned what SFINAE means!

We talked about the base class noncopyable . By providing both a useful idiom and straightforward usage that catches the eye of anyone reading the code, it definitely deserves to be used regularly. The omission of a copy constructor and assignment operator in classes that need them, whether through the need for customized copying/assignment or the prohibition thereof, is all too common in code, costing lots of frustration, time, and money.

This is one of the shortest chapters in the book, and I suspect that you've read through it fairly quickly. It pays you back fast, too, if you start using these utilities right away. There are other utilities in Boost.Utility, which I haven't covered here. You might want to surf over to the Boost Web site and have a look at the online documentation to see what other handy tools there would suit you well in your current work.


Library 4. Operators

How Does the Operators Library Improve Your Programs?

Operators

Usage

Operators Summary


How Does the Operators Library Improve Your Programs?

  • Provides a complete set of comparison operators

  • Provides a complete set of arithmetic operators

  • Provides a complete set of operators for iterators

Among the operators defined in C++, there are a number of related sets. When you encounter a class with one operator from one of these sets, you typically expect to find the others, too. For instance, when a class provides operator== , you expect to find operator!= and probably operator< , operator<= , operator> , and operator>= . Sometimes, a class only provides operator< in order to define an ordering so objects of that class can be used in associative containers, but that often leaves class users wanting more. Likewise, a class with value semantics that provides operator+ but not operator+= or operator- is limiting its potential uses. When you define one operator from a set for your class, you should typically provide the remaining operators from that set to avoid surprises . Unfortunately, it is cumbersome and error prone to augment a class with the many operators needed to support comparisons or arithmetic, and iterator classes must provide certain sets of operators according to the iterator category they model just to function correctly.

Besides the tedium of defining the number of operators needed, their semantics must be correct to meet users' expectations. Otherwise, the class is, for all practical purposes, unusable. We can relieve ourselves from doing it all by hand, though. As you know, some of the operators are typically implemented in terms of others, such as implementing operator+ in terms of operator+= , and that suggests that some automation of this task is possible. In fact, that is the purpose of Boost.Operators. By allowing you to define only a subset of the required comparison or arithmetic operators, and then defining the rest for you based upon those you provide, Boost.Operators enforces the correct operator semantics, and reduces your chance of making mistakes.

An additional value of the Operators library is the explicit naming of concepts that apply for different operations, such as addable for classes supporting operator+ and operator+=, shiftable for classes supporting operator<< and operator>> , and so on. This is important for two reasons: A consistent naming scheme aids understanding; and these concepts, and the classes named after them, can be part of class interfaces, clearly documenting important behaviors.

How Does Operators Fit with the Standard Library?

When using the Standard Library containers and algorithms, one typically supplies at least some relational operators (most commonly operator< ) to enable sorting, and thus also storage of the type in sorted, associative containers. A common practice is to define only the bare minimum of the required operators, which has the unfortunate side effect of making the class less complete, and harder to understand. On the other hand, when defining a full set of operators, there is a risk of introducing defective semantics. In these cases, the Operators library helps to make sure that the classes behave correctly, and adhere to the requirements of both the Standard Library and the users of the type. Finally, for types that define arithmetic operators, there are a number of operators that are well suited to be implemented in terms of other operators, and Boost.Operators is of great use here, too.