Concepts Lite

Concepts Lite

This is a crosspost from www.ModernesCpp.com.

We stay in the year 2020. We will get with high probability concepts lite. 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, 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 lite

With C++20 we will get concepts lite. Although concepts lite are in the first implementations simplified 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 lite are called 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 lite are similar to Haskells type classes. Concepts lite 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 lite, 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.

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.

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

Concepts lite for functions, classes, and members of a class

Concepts lite 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 lite 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 lite 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 lite 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.  

Marco Zanella

Ph.D. Computer Science

7 年

Am I the only one who sees this as an idea with something in common to traits?

要查看或添加评论,请登录

Rainer Grimm的更多文章

  • My ALS Journey (17/n): Christmas Special

    My ALS Journey (17/n): Christmas Special

    Today, I have a special Christmas gift. My ALS Journey so far Make the Difference Let’s do something great together:…

  • std::execution

    std::execution

    std::execution, previously known as executors or Senders/Receivers, provides “a Standard C++ framework for managing…

    1 条评论
  • C++26 Core Language: Small Improvements

    C++26 Core Language: Small Improvements

    There are more small improvements in the C++26 language, which you should know. static_assert extension First, here’s…

  • My ALS Journey (16/n): Good Bye Training / Hello Mentoring

    My ALS Journey (16/n): Good Bye Training / Hello Mentoring

    In 2025, I will no longer offer C++ classes. Instead, I will only offer C++ mentoring in the future.

    1 条评论
  • Placeholders and Extended Character Set

    Placeholders and Extended Character Set

    Placeholders are a nice way to highlight variables that are no longer needed. Additionally, the character set of C++26…

    4 条评论
  • Contracts in C++26

    Contracts in C++26

    Contracts allow you to specify preconditions, postconditions, and invariants for functions. Contracts should already be…

    5 条评论
  • Mentoring as a Key to Success

    Mentoring as a Key to Success

    I know that we are going through very challenging times. Saving is the top priority.

  • Reflection in C++26: Determine the Layout

    Reflection in C++26: Determine the Layout

    Thanks to reflection, you can determine the layout of types. My examples are based on the reflection proposal P2996R5.

    5 条评论
  • My ALS Journey (15/n): A typical Day

    My ALS Journey (15/n): A typical Day

    You may wonder how my day looks. Let me compare a day before ALS with a current day.

    3 条评论
  • Reflection in C++26: Metafunctions for Enums and Classes

    Reflection in C++26: Metafunctions for Enums and Classes

    Today, I continue my journey through reflection in C++26 and play with enums and classes. The names of the…

    2 条评论

社区洞察

其他会员也浏览了