Concepts

Contents[Show]

We stay in the year 2020. We will get with high probability concepts. Of course, waterproof statements about the future are difficult but the statement is from Bjarne Stroustrup (Meeting C++ 2016 at Berlin).

The classical concepts

The key idea of generic programming with templates is, to define functions and classes that can be used with different types. But it will often happen that you instantiate a template with the wrong type. The result may be a cryptic error message that is many pages long. Sadly to say, but templates in C++ are known for this. Therefore, classical concepts were planned as one of the great features of C++11. They should allow you to specify constraints for templates that can be verified by the compiler. Thanks to their complexity, the were remove in July 2009 from the standard:  "The C++0x concept design evolved into a monster of complexity." (Bjarne Stroustrup)

Concepts

With C++20 we will get concepts. Although concepts are in the first implementations simplified classical concepts, they have a lot to offer.

They

  1. empowers programmer to directly express their requirements as part of the interface.
  2. supports the overloading of functions and the specialisation of class templates based on the requirements of the template parameters.
  3. produces drastically improved error messages by comparing the requirements of the template parameter with the applied template arguments.
  4. can be used as placeholders for generic programming.
  5. empowers you to define your own concepts.

Although concepts are sometimes called concepts lite, their functionality is by no means lite and I can not be present them in one post. Therefore, I will postpone the points 4 and 5 to later posts. Promised!

You will get the benefit without additional compile time or runtime time of the program. Concepts are similar to Haskells type classes. Concepts will describe semantic categories and not syntactic restrictions. For types of the standard library, we get library concepts such as DefaultConstructible, MoveConstructible, CopyConstructible, MoveAssignable, CopyAssignable,  or Destructible. For the containers, we get concepts such as ReversibleContainer, AllocatorAwareContainer, SequenceContainer, ContinousContainer, AssociativeContainer, or UnorderedAssociativeContainer. You can read the about concepts and their constraints here: cppreference.com.

Before I present concepts, let me have a view at Haskell's type classes.

Type classes in Haskell

Type classes are interfaces for similar types. If a type is a member of a type class, it has to have specific properties. Type classes play a similar role for generic programming as interfaces play for object-oriented programming. Here you can see a part of Haskell's type classes hierarchy.

typeclass

What is special for a type if it is a member of a type class Eq? Eq stands for equality and requires from its members:

 

class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    a == b = not (a /= b)
    a /= b = not (a == b)

Eq requires that its types have to support the functions  equality (==) and inequality (/=). The expression  a -> a -> Bool stands for the signature of the function. The function takes two identical types a and returns a Boolean: Bool. But for a concrete type, it is sufficient to implement equality or inequality because equality will be mapped to inequality and vice versa. The default implementations of both functions are provided in the two last lines.

By the following code snipped the built-in type Bool becomes an instance of the type class Eq.

instance Eq Bool where
    True == True = True
    False == False = True
    _ == _ = False

 

Haskell's type classes build a hierarchy. The type class  Ord is a subclass of the type class Eq. Therefore, instances of the type class Ord have to be members of the type class Eq and have in addition support the comparison operators.

Haskell is able to automatically create the necessary functions of some type classes. Therefore, I can compare the values Morning and Afternoon of the data type day for equality and output them. I have only to derive Day from the type class Eq and Show.

data Day= Morning | Afternoon
     deriving (Eq,Show)

Now I can directly test my data type Day in the interactive Haskell Shell. The formal name for the interactive Shell is REPL. Many programming languages such as Python or Perl have a REPL. REPL stands for Read Evaluate Print Loop.

 day

Type classes in Haskell have a lot more to offer. For example, you can define your own type classes.

Concepts for functions, classes, and members of a class

Concepts are part of the template declaration.

Functions

The function template sort requires

template<Sortable Cont>
void sort(Cont& container){...}

that the container has to be Sortable. It is also possible to define the requirement to the template parameters more explicitly:

 

template<typename Cont>
  requires Sortable<Cont>()
void sort(Cont& container){...}

 

Sortable has to be a constant expression that is a predicate. That means that the expression has to be evaluable at compile time and has to return a boolean.

If you invoke the sort algorithm with a container lst that is not sortable, you will be a unique error message from the compiler.

std::list<int> lst = {1998,2014,2003,2011};
sort(lst); // ERROR: lst is no random-access container with <

 

You can use concepts for all kind of templates.

Classes

Therefore, you can define a class template MyVector that will only accept objects as template arguments:

template<Object T>
class MyVector{};

MyVector<int> v1; // OK
MyVector<int&> v2 // ERROR: int& does not satisfy the constraint Object

 

Now, the compiler complains that the a pointer (int&)  is no object. MyClass can be further adjusted.

Members of a class

template<Object T>
class MyVector{
  ...
  requires Copyable<T>()
  void push_back(const T& e);
  ...
};

 

Now the method  push_back  from MyVector requires that the template argument has to be copyable.

Extended functionality

A template can have more the one requirements for its template parameters.

More than one requirement

template <SequenceContainer S,EqualityComparable<value_type<S>> T>
Iterator_type<S> find(S&& seq, const T& val){...}

The function template find has two requirements. At one hand, the container has to store its elements in a linear arrangement (SequenceContainer), at the other hand the elements of the container has to be equal comparable: EqualityComparable<value_type<S>>).

Concepts supports the overloading of functions.

Overloading of functions

template<InputIterator I>
void advance(I& iter, int n){...}

template<BidirectionalIterator I>
void advance(I& iter, int n){...}

template<RandomAccessIterator I>
void advance(I& iter, int n){...}

std::list<int> lst{1,2,3,4,5,6,7,8,9};
std::list<int>:: iterator i= lst.begin();
std::advance(i,2);   // BidirectionalIterator

 

The function template advance puts its's iterator iter n positions further. Depending, if the iterator is a forward, a bi-directional of a random access iterator different function templates will be applied. If I use a std::list, the BidirectionalIterator will be chosen.

Concepts also support the specialisation of class templates.

Specialisation of class templates

template<typename T>
class MyVector{};

template<Object T>
class MyVector{};

MyVector<int> v1; // Object T
MyVector<int&> v2 // typename T

Therefore, the compiler maps MyVector<int&> v2 to the general template in the first line; the compiler maps MyVector<int> v1 in the contrary to the specialisation template<Object T> class MyVector{}.

What's next?

Haskell has the type class Monad.  A known instance is the Maybe Monad. Why did I write about that stuff? That is simple. C++17 gets with the data type std::optional a Monad that represent a calculation the can or can not return a result. The details about std::optional will follow in the next post.  

Comments   

0 #1 Rosemarie 2017-03-10 02:56
Hello there, You have done a fantastic job.
I'll certainly digg it and for my part recommend to my friends.
I am sure they'll be benefited from this site.
Quote

Add comment


My Newest E-Book

Latest comments

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 346

All 278869

Currently are 149 guests and no members online