Archive for May, 2007

ConceptGCC — BoostCon Edition is now available

May 10, 2007

BoostCon 2007 is coming up next week, and will be full of interesting sessions on Boost and C++0x. I’ll be giving a half-day tutorial on concepts, and have rolled a special version of ConceptGCC just for this occasion (and, to fix a critical bug or two that affects my slides). The BoostCon edition of ConceptGCC contains the following improvements:

  • The range-based for loop now deals with temporary containers appropriately.
  • Rvalue-reference arguments in associated functions now forward as an rvalue.
  • The iterator concepts have been simplified and expanded in scope, providing better support for proxies; vector<bool>::iterator is again a RandomAccessIterator.
  • Added Semiregular and Regular concepts.
  • Added support for delegating constructors (for real this time).
  • Added the DerivedFrom concept.

The DerivedFrom concept

May 8, 2007

We recently decided that we needed a new concept, DerivedFrom, to express the requirement for an inheritance relationship between two types. This concept has the following definition:

  concept DerivedFrom<typename Derived, typename Base> { /*unspecified*/ }

DerivedFrom is a compiler-support concept, like SameType. We expect that most of its uses will be to intermingle the object-oriented and generic programming facilities of C++0x, e.g.,

  template<typename T>
  requires DerivedFrom<T, Shape>
  void draw(T& shape) {
    // Can use Shape's member functions via "shape" object.
  }

DerivedFrom is now supported (albeit “lightly tested”) in the development version of ConceptGCC.

Requirement Propagation and CopyConstructible

May 3, 2007

The concepts proposal contains a feature called “requirement
propagation” (formerly referred to as “constraint propagation”), which
implicitly defines constraints based on the declaration of a
template. If you didn’t know that requirement propagation existed,
don’t worry; it’s a behind-the-scenes feature that reduces the size of
requirements clauses.

There is one aspect of requirement propagation that we would like to
change. As of N2193, [temp.req.prop] paragraph 2 says:

For every type T that appears as an argument or return type in a
function declarator, the requirement std::MoveConstructible<T> is
implicitly added to the requirements clause. [ Example:

    template<EqualityComparable T>
    bool eq(T x, T y); // implicitly adds requirement CopyConstructible<T>

--end example ]

For various reasons, this feature is problematic and has been removed from ConceptGCC. This change will break some “existing” concepts code. For example, the function “negate” below is currently (according to N2193) well-formed:

  auto concept Negatable<typename T> {
    T operator-(T);
  }

  template<Negatable T>
  T negate(const T& x) { return -x; }

ConceptGCC used to compile this. With today’s development version of ConceptGCC, however, we get an error message:

  beep.C: In function 'T negate(const T&)':
  beep.C:6: error: constructor 'T::T(const T&)' is inaccessible

To remedy the error, add a CopyConstructible requirement, so that “negate” can return its value. Formerly, the
compiler would have added this requirement:

  template<Negatable T> requires CopyConstructible<T>
  T negate(const T& x) { return -x; }

The New Old Iterator Concepts

May 3, 2007

The C++ community has known for a long time that the STL iterator requirements are too strict. There have been various attempts at refactoring the iterator concepts to loosen the requirements (thus permitting more iterator-like entities to be iterators).

In Oxford, Jeremy Siek presented an alternative iterator concept taxonomy that separated access from traversal (the main known issue with the existing iterator requirements), describing using Concepts. Better yet, he updated all of the STL algorithms to use this new concept taxonomy, proving how well it works.

Since then, Jeremy Siek and Alex Stepanov realized that an even simpler change would suffice: in the existing iterator concepts, as modeled by ConceptGCC up until a few days ago, dereferencing a ForwardIterator had to return a “true” C++ reference (e.g., value_type const&) . It turns out that this requirement is very, very rarely used in the STL. So, Jeremy made a very simple change: ForwardIterators, like InputIterators, only require that operator* return something convertible to value_type. Mutable iterators require that one can assign a value_type to the result of operator*. Now, proxy iterators (like the infamous vector<bool>::iterator) can meet all of the iterator concept requirements!

ConceptGCC now has these new, old iterator concepts. With just a minor change, Jeremy and Alex fixed the major problems with iterator concepts… and it’s completely implemented in the development verson of ConceptGCC. Huzzah!