RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Easier C++: An Introduction to Concepts : Page 3

C++0x concepts bring the full power of the Generic Programming paradigm to C++, making templates more expressive, easier to write, and easier to use. Spectacularly poor template error messages are a thing of the past!

Author's Side of the Contract
When the author of a template places requirements on that template, the author is also bound by the terms of the contract. In particular, the author cannot use an object of type T with any operations not specified in the contract. With the min() function, for example, the body of the function can use only the < operator on objects of type T, because only the < operator is specified by the LessThanComparable concept. Suppose you tried to implement a max() function with LessThanComparable as follows:

template<typename T>
requires LessThanComparable<T>
const T& max(const T& x, const T& y) {
  return x > y? x : y; // error: no operator>(T, T)
In this example, the author specified in the contract that the type T would provide a '<' operator, but the template body uses '>'. The compiler will produce an error message when it processes the template stating that no such '>' operator exists. Therefore, the template author is bound by the same contract as the user, and there cannot be any surprises where the template author states one requirement in the contract but uses a slightly different operation in the implementation. This is exactly the kind of problem that occurs with template libraries today: Because most types that max() would be tested with will have both less-than and greater-than operations, the latent error—that the function requires less-than but uses greater-than—is unlikely to be detected by testing. With concepts, however, the compiler detects this form of error immediately.

Because both the template author and user are held to the same contract, the compiler can provide an extremely important guarantee: If both the template's implementation and the use of the template meet the contract's requirements, the instantiation of that template will not fail. There are two practical effects to this guarantee. First, concepts eliminate the spectacularly poor error messages produced by long instantiation backtraces, because the failures occur before template instantiation is even attempted. Second, both users and library authors can have a far greater level of confidence in template libraries using concepts than in the corresponding pre-concept libraries, because the compiler takes a more active role in verifying the correctness of templates.

The Perimeter of a Polygon
Listing 2 contains a simple algorithm that computes the perimeter of the polygon it is given, by summing the lengths of each of the sides of the polygon. Polygons are described by the Polygon concept, which provides functions that determine the number of sides and the length of a given side.

The Polygon concept's requirements can be satisfied by many different data types. For example, you can implement a simple triangle class that can be passed to the perimeter() function:

class triangle {
  int sides[3];

int num_sides(const triangle& tri) { return 3; }
int side_length(const triangle& tri, int index) { 
  return tri.sides[index]; 

concept_map Polygon<triangle> { }
The triangle class provides the operations required by the Polygon concept, num_sides() and side_length(). Note, however, that while the Polygon concept expects side_length() to return a double, triangle's version of side_length() returns an int. This is not an error. Concept maps provide one level of conversions, which will automatically convert the int returned by triangle's num_sides() into the double expected by users of the Polygon concept. This way, minor mismatches in the interface between the template user and the template author are resolved automatically in the concept map, making constrained templates more widely applicable.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date