Concept HOWTO

Defining a concept

template <typename Model>
struct MyConcept {
  // We declare a type.
  typedef typename Model::SomeType SomeType;
  typedef typename Model::ReturnType ReturnType;

#ifdef GEN_DOC
  //We declare the needed functions
  ReturnType operator()(SomeType&, int);
#else
  typedef void static_check;

  static_assert(std::is_same<ReturnType,
                             std::declval<SomeType&>()(0)>::value,
                "operator()(SomeType&, int) does not return ReturnType");
#endif
};

template <typename T>
struct MyModel {
  typedef void NoModel;
};

Defining models

struct A {
  int operator()(int) {
    return 0;
  }
};

template <>
struct MyModel<A> {
  struct Model {
    typedef A SomeType;
    typedef int RetType;
  };
};

Requiring a model

template <typename T,
          typename Model = MyModel<T>::Model>
void foo(T) {
  //We have a model, but we need to require this model to check.
  typedef typename Model::static_check require;

  //...
}

Or for a class:

template <typename T>
struct Foo {
  typedef typename MyModel<T>::Model::static_check require;

  //...
};

Making automatic models

In case it is possible to know automatically a model, then we can do as follow.

template <typename T,
          bool = is_callable_with<T&, int>::value>
struct MyModel;

template <typename T>
struct MyModel<T, false> {
  typedef void NoModel;
};

template <typename T>
struct MyModel<T, true> {
  struct Model {
    typedef A SomeType;
    typedef decltype(std::declval<T&>()(std::declval<int>())) RetType;
  };
};

Writing an archetype

TODO