C++20: Concepts - What we don't get

Contents[Show]

The Template Introduction from the Concepts TS is a new way to use concepts. This syntactic variant is not included in the Concepts Draft and, therefore, in the C++20 standard. But, I don't know what the farther away future brings.

 

 TimelineCpp20Concepts

Template Introduction

Let me first start with a short riddle. Which one, of the following syntactic variants, is not possible with the concepts draft?

 

template<typename T>                                  // (1)
requires Integral<T>
T gcd(T a, T b){
    if( b == 0 ) return a;
    else return gcd(b, a % b);
}

template<typename T>                                  // (2)
T gcd1(T a, T b) requires Integral<T>{
    if( b == 0 ){ return a; }
    else return gcd(b, a % b);
}

template<Integral T>                                  // (3)
T gcd2(T a, T b){
    if( b == 0 ){ return a; }
    else return gcd(b, a % b);
}

Integral auto gcd3(Integral auto a, Integral auto b){ // (4)
    if( b == 0 ){ return a; }
    else return gcd(b, a % b);
}

Integral{T}                                           // (5)
Integral gcd(T a, T b){
  if( b == 0 ){ return a; }
  else{
    return gcd(b, a % b);
  }
}

Maybe, you don't know. So let me name the five variants.

  1. Requires clause
  2. Trailing requires clause
  3. Constrained template parameters
  4. Abbreviated Function Templates
  5. Template Introduction

I assume you have chosen the most obscure one: Template Introduction. You are right. Maybe we get it with a later C++ standard, but I'm highly sceptical. In my talks in the last year, I heard no one complaining that they are not part of C++20. I'm also not a big fan of Template Introduction because they introduced a new asymmetry, and you know, I'm not a fan of asymmetries.

The Asymmetry

Instead of declaring your constrained template by using template<Integral T>, you can just Integral{T}. Here, you see the asymmetry. You can only use Template Introduction with concepts (constrained placeholders) but not with auto (unconstrained placeholders). The following example makes my point. This and the following example is based on the previous concepts TS specification and compiled with the GCC.

 

// templateIntroduction.cpp

#include <type_traits>
#include <iostream>

template<typename T>
concept bool Integral(){
  return std::is_integral<T>::value;
}

Integral{T}                            // (1)
Integral gcd(T a, T b){
  if( b == 0 ){ return a; }
  else{
    return gcd(b, a % b);
  }
}

Integral{T}                            // (2)
class ConstrainedClass{};

/*

auto{T}                                // (4)
auto gcd(T a, T b){
  if( b == 0 ){ return a; }
  else{
    return gcd(b, a % b);
  }
}

auto{T}                                // (5)
class ConstrainedClass{};

*/


int main(){
  
  std::cout << std::endl;
  
  auto res= gcd(100, 10); 

  ConstrainedClass<int> constrainedClass;
  ConstrainedClass<double> constrainedClass1;  // (3)
  
  std::cout << std::endl;

}

I use Template introduction for the function template gcd (line 1) and the class template ConstrainedClass (line 2). As expected,  the concept will kick in if I try to instantiate ConstraintedClass for double (line 3).

templateIntroductionError

 

I don't like it that I can not just replace Integral with auto such as in lines 4 and 5. Up to this point in my posts to concepts, I used constrained placeholders (concepts) and unconstrained placeholders (auto) interchangeably. This straightforward principle is gone with Template Introduction.

Of course, I could easily overcome this restriction by defining a concept that always evaluated to true.

// templateIntroductionGeneric.cpp

#include <iostream>
#include <string>
#include <typeinfo>
#include <utility>

struct NoDefaultConstructor{               // (5)
    NoDefaultConstructor() = delete;
};

template<typename T>                       // (1)
concept bool Generic(){
  return true;
}

Generic{T}                                 // (2)
Generic gcd(T a, T b){
  if( b == 0 ){ return a; }
  else{
    return gcd(b, a % b);
  }
}

Generic{T}                                 // (3)
class ConstrainedClass{
public:
  ConstrainedClass(){
    std::cout << typeid(decltype(std::declval<T>())).name()   // (4)
              << std::endl;
  }
};


int main(){
  
  std::cout << std::endl;
  
  std::cout << "gcd(100, 10): " << gcd(100, 10) << std::endl;
  
  std::cout << std::endl;
 
  ConstrainedClass<int> genericClassInt;
  ConstrainedClass<std::string> genericClassString;
  ConstrainedClass<double> genericClassDouble;
  ConstrainedClass<NoDefaultConstructor> genericNoDefaultConstructor;
  
  std::cout << std::endl;

}

 

Generic (line 1) is a concept that returns true for all types. Now, I can unify the syntax and define an unconstrained function template (line 4) and an unconstrained class template (line 3). Honestly, the terms unconstrained or constrained function templates or class template are not official. I coined them for simplicity reasons.

The expression typeid(decltype(std::declval<T>())).name() (line 4)  may look weird to you. std::declvar<T> (C++11) converts the type parameter T into a reference type. Thanks to the reference type, you can use it in a decltype expression to invoke any member function on T without constructing T. It works even for a type T without a default constructor (line 5). In my case (line 4), I invoked the constructor on the reference type to get the string representation of the type parameter T. Here is the output of the program with GCC.

templateIntroductionGeneric2

What's next?

One big topic is left to complete the story to concepts: define your concept. Most of the times, you reinvent the wheel because C++20 has many pre-defined concepts. Anyway, I present with my next post the pre-defined concepts and who you can define your one.

 

This is my last post for 2019. You hear from me on 12.01.2020. If your hopefully contemplative time is too contemplative, here are about 300 posts to modern C++: StartHere

 

Thanks a lot to my Patreon Supporters: Paul Baxter,  Meeting C++, Matt Braun, Roman Postanciuc, Venkata Ramesh Gudpati, Tobias Zindl, Marko, G Prvulovic, Reiner Eiteljörge, Reinhold Dröge, Abernitzke, Richard Ohnemus, Frank Grimm, Sakib, Broeserl, António Pina, Markus Falkner, Darshan Mody, Sergey Agafyin, Андрей Бурмистров, and Jake.

 

Thanks in particular to:   crp4

 

   

Get your e-book at Leanpub:

The C++ Standard Library

 

Concurrency With Modern C++

 

Get Both as one Bundle

cover   ConcurrencyCoverFrame   bundle
With C++11, C++14, and C++17 we got a lot of new C++ libraries. In addition, the existing ones are greatly improved. The key idea of my book is to give you the necessary information to the current C++ libraries in about 200 pages. I also included more than 120 source files.  

C++11 is the first C++ standard that deals with concurrency. The story goes on with C++17 and will continue with C++20.

I'll give you a detailed insight in the current and the upcoming concurrency in C++. This insight includes the theory and a lot of practice with more than 140 source files.

 

Get my books "The C++ Standard Library" (including C++17) and "Concurrency with Modern C++" in a bundle.

In sum, you get more than 700 pages full of modern C++ and more than 260 source files presenting concurrency in practice.

 

Get your interactive course

 

Modern C++ Concurrency in Practice

C++ Standard Library including C++14 & C++17

educative CLibrary

Based on my book "Concurrency with Modern C++" educative.io created an interactive course.

What's Inside?

  • 140 lessons
  • 110 code playgrounds => Runs in the browser
  • 78 code snippets
  • 55 illustrations

Based on my book "The C++ Standard Library" educative.io created an interactive course.

What's Inside?

  • 149 lessons
  • 111 code playgrounds => Runs in the browser
  • 164 code snippets
  • 25 illustrations

Add comment


My Newest E-Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 3155

All 3204249

Currently are 312 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments