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


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

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!

Associated Types
The implementation of perimeter() works with the triangle class, but it is suboptimal; despite the fact that the sides of the triangle are specified in terms of integers, all of the computation in perimeter() is performed via floating-point arithmetic. To solve this problem, the algorithm should instead perform the computation using the same type that the polygon uses to express the lengths of its sides, which may vary from one type to another.

Concepts provide a way to express such types, which vary from one use of a concept to another: associated types. Associated types are declared within the body of a concept via the typename keyword (using the same syntax as template type parameters), and can be used to describe operations within the concept. You can now revise the Polygon concept to introduce an associated type named length_type, which is used to express the length of a single side in the polygon, and therefore is the return type of the side_length() operation:

concept Polygon<typename P> {
  typename length_type
  int num_sides(const P&);
  length_type side_length(const P&, int index);
Because the types of concept operations are important wherever the concepts are used, you can refer to an associated type as a nested type within the concept. For example, an updated perimeter() algorithm should refer to the length_type of the Polygon concept explicitly, rather than using double:

template<typename P>
requires Polygon<P>
Polygon<P>::length_type perimeter(const P& poly) {
  Polygon<P>::length_type sum = 0; // error!
  for (int i = 0; i < num_sides(poly); ++i)
    sum += side_length(poly, i); // error!
  return sum; // error!
Here, the uses of double are replaced with Polygon<P>::length_type, which has made the algorithm capable of handling different length types, and therefore more reusable. However, this change has introduced some new errors that will be detected by the compiler. Previously, the algorithm was relying on the built-in operations provided by double: construction from an integer, addition via +=, and copy-construction of the return value. With an arbitrary length_type, you can no longer assume that all of these operations are available. They have to be specified as requirements on the length type, which the user's length type must satisfy.

Member-Function Requirements
To express the length type's requirements, we introduce another new concept, Numeric. The Numeric concept provides the essential operations required to sum a value:

auto concept Numeric<typename T> {
  T::T(const T&);              // copy construction
  T::T(int);                   // construction from an int
  T::~T();                     // destructor
  T& operator+=(T&, const T&); // addition
The first three operations in the Numeric concept require a copy constructor (which can be satisfied by a built-in initialization), the ability to construct a value of type T from an int, and the ability to destroy an object of type T. Each of these operations is stated using member function syntax with the T:: prefix, specifying that these operations apply to objects of type T. The same syntax can be used to describe specific member functions requirements (for example, T::clone()).

Armed with the Numeric concept, you can express the perimeter() algorithm's full requirements as:

template<typename P>
requires Polygon<P> && Numeric<Polygon<P>::length_type>
Polygon<P>::length_type perimeter(const P& poly);
The "&&" in the requires clause states that both requirements must be satisfied for the algorithm to be usable, that is, the type P must be a Polygon and its length_type must be Numeric. Any number of different requirements can be added to a template using "&&", including multiple requirements on the same types.

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