Getting started


  • A compiler supporting a majority of C++2011.
    • GCC >= 4.5.1
    • Known not to work (yet):
      • Visual Studio 2010 and before (e.g. no support of variadic template parameters)
      • Xcode 4 and before (old version of GCC)
      • Clang (has probably enough features, but does not support any C++2011 standard library)
      • ICC 11.1.072 and before
      • GCC 4.4.* and before (e.g. std::declval is missing from the library)
  • A standard C++ library supporting a majority of C++2011.
    • GCC's libstdc++
    • Known not to work (yet):
      • Clang's libc++
    • Untested:
      • STLport


This describes the installation for development versions of Catsfoot. The run-time shared library contains only testing tools and does not need to be shipped with the software.

Nightly build versions are available from page Download.

From package

There are nightly build packages for

  • Fedora 14 x86 and x86_64
  • Fedora rawhide x86 and x86_64
  • Ubuntu 10.04 x86 and x86_64
  • Ubuntu 10.10 x86 and x86_64
  • Debian sid x86 and x86_64

Those can be installed with rpm or dpkg depending on the distribution.

Gentoo users can install it with:

# emerge -uv layman
# sed -i "/^overlays *:/a" /etc/layman/layman.cfg
# layman -a vfrd
# echo "dev-libs/catsfoot ~$(portageq envvar ARCH)" >>"${EPREFIX}/etc/portage/package.keywords"
# emerge -u dev-libs/catsfoot

From source

Catsfoot uses Autoconf and Automake, so the installation is pretty standard.

$ xz -dc /path/to/catsfoot-0.1.tar.gz | tar xf -
$ ./catsfoot-0.1/configure --prefix="/path/where/to/install"
$ make install

From the repository

We discourage using the version of the repository as some versions might not have passed the test suite. Use a nightly build source package instead.

Using Catsfoot in your build system

Catsfoot installs two pkg-config package descriptions:

  • catsfoot is used only for supporting concepts. It is used for shipped binaries of your project. In this way it does not depend on any run-time library, but still provides static concept checking.
  • catsfoot-rt is used for your test suite. It links to Catsfoot's runtime library.

Automake & Autoconf

In your file, you should have a line such as:


Then in your file, should have for example (for "check" program "mytest"):


The manual page of pkg-config contains more information.

Do not forget to call "configure" with "CXX='g++ -std=c++0x'", or make your configure script to add "-std=c++0x" automatically.


Scons wiki page PkgConfig explains how to use pkg-config in your project.

By hand

For example:

g++-4.6.0 -std=c++0x `pkg-config --cflags --libs catsfoot-rt`

My first test program

Lets write a concept for a set. We can insert an element inside the set, and we can test whether an element has been inserted.

# include <catsfoot.hh>

// We define some tools we will need in our concept.
// - has_member_element_type<T> checks for member type "T::element_type"
// - member_has(cv-qualifier T&, Args...) is an alias to
//   "T::has(Args...) cv-qualifier"
// - member_insert(cv-qualifier T&, Args...) is an alias to
//   "T::insert(Args...) cv-qualifier"

namespace cf = catsfoot;

// We define a concept "set" for a type we call "Set"
template <typename Set>
struct set: public cf::concept {
  // We define "element_type" to be an alias to Set::element_type if
  // it ever exists. Using has_member_element_type makes sure that
  // we will not get any strange error message in case Set::element_type
  // was not a type, or was not declared.
  // This alias makes the concept more concise, but is not necessary.
  typedef typename has_member_element_type<Set>::member_type element_type;

  // is_callable<C> is a predicate. We declare some aliases to the
  // predicate calling members Set::has(element_type) const, and
  // Set::insert(element_type). Since the predicates will be
  // reused several times, it helps us to make the concept definition
  // more concise. But it is not necessary.
  typedef cf::is_callable<member_has(const Set&, element_type)> has;
  typedef cf::is_callable<member_insert(Set&, element_type)> insert;

  // We declare our static requirements
  typedef cf::concept_list<
    // Set::element_type must exist and define a type.
    // Set::has(element_type) const must be callable
    // Its result should be implicitly convertible to bool.
    std::is_convertible<typename has::result_type, bool>,
    // Set::insert(element_type) must be callable
    // We require "operator==(element_type, element_type)" to be defined
    > requirements;

  // For all element e and f, with a reference to set s, this axiom should
  // hold.
  static void insertion(const element_type& e, const element_type& f, Set& s) {
    // Was f already inside?
    bool res = s.has(f);
    if (e != f)
      // if e is not equal to f, then insertion of e should insert nor
      // remove f.
      axiom_assert(res == s.has(f));

    if (e == f)
      // if e and f are equal, then f should be in the set.
      axiom_assert(true == s.has(f));

  // Axioms are usually just static members. We need to declare them as
  // axioms for the test driver to use them.

Note that this concept is does not specify everything from the commonly used set implementations. For example, according to the axioms, a type where has is always true for any element and where insert does not perform any operation, will model the concept set.

Let's now define a very simple implementation of set. You can note that we can reuse any set type as long as it implements at least concept set. The type will actually implement a more specific algebra.

template <typename T>
struct slow_set {
  // Required by the concept.
  typedef T element_type;

  // Although this is not required by the concept, we provide
  // some constructors.
  slow_set() = default;
  slow_set(const slow_set&) = default;

  // Required by the concept
  void insert(const T&);
  bool has(const T&) const;

  std::vector<T> values;

  // Because:
  // - we do not resize the vector, we do not need default constructible
  // - we do not use move semantic, we can require copy
  // - we do not replace, we do not need assignment
    cf::concept_list<cf::is_constructible<T(const T&)>,
                     cf::equality<T> >

template <typename T>
void slow_set<T>::insert(const T& t) {
  for (auto i : values) {
    if (i == t)

template <typename T>
bool slow_set<T>::has(const T& t) const {
  for (auto i : values) {
    std::cerr << t << " == " << i << std::endl;
    if (i == t)
      return true;
  return false;

template <typename T>
slow_set<T>::slow_set(std::initializer_list<T> l) {
  for (auto i : l) {

We now want to claim that for any T, slow_set<T> is a set. We can claim this because we made sure that slow_set<T> was not instantiated with an incompatible type through instantiation of slow_set<T>::requirements. The claim is made through type traits.

namespace catsfoot {
  template <typename T>
  struct verified<set<slow_set<T> > >
    : public std::true_type {

To test this claim we now write a test program. We just make a small program that defines the data set we want to use and call the test driver for the concepts we want to check. We could define very complex random term generators, but for now, we will just give a list of sample data.

#include <limits>

int main() {
  using cf::list_data_generator;
  using cf::choose;

  // To get better error messages, we should first statically check that
  // we are testing a valid claim.
  cf::assert_concept(set<slow_set<int> >{});

  auto generator =
    // The generator can generate either:
    // - sets of type slow_set<int>
    (list_data_generator<slow_set<int> >(
      {slow_set<int>{}, slow_set<int>({0, 1}),
       slow_set<int>({0, 0}), slow_set<int>({1, 0})}),
    // - or integers
     list_data_generator<int>({0, 1, 2, 3, -1, -2,

  // We now test claim "set<slow_set<int> >" against generator.
  bool ret = cf::test_all<set<slow_set<int> > >(generator);

  // In our case, the implementations of the set was complete, so
  // we want to verify that we did cover all conditions in the axioms.
  ret = ret && cf::check_unverified();

  return ret?0:1;

This is the simplified picture of what testing looks like. The tutorials will cover each point in detail.