Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we use Concept&Constraint

Tags:

c++

c++20

I don't really understand why C++20 provides such a feature like that. I need someone to point out how to use this feature gracefully. Here is an example:

template<typename T>
concept LessCompareable=requires(const T& lhs, const T& rhs)
{
      {lhs<rhs}->bool;
};

Now I've defined a concept. Then I'll constraint a function template like this: (well, let's name it comp, in fact it just like std::min)

template<typename T>
const T& comp(const T& a , const T& b) requires LessCompareable<T>
{return a<b?a:b;}

So the problem is if you call this like

std::thread a,b;
cout<<comp(a,b);

complie error occured

but if we don't use constraint, CE will occur, too.

So that makes me puzzled, both of them have CE, then why I should use constraints?

I think if I want to clean up error messages, I can use SFINAE.

like image 219
con ko Avatar asked Apr 05 '18 08:04

con ko


2 Answers

The purpose of constraints is to allow you to specify pre-conditions on operations using built-in language constructs. Those pre-conditions could be checked by the compiler and either:

  1. You'll get a clear error message.
  2. The overload will not be considered in overload resolution (yes, one more way to do SFINAE).

The error messages are nice to have, but the new pre-condition checks for #2 are the real meat of this. What you'd need to do before C++20 to obtain the same effect is something like this:

template<typename T,
         std::enable_if_t<has_less_than_op<T>::value, int> = 0>
const T& comp(const T& a , const T& b) 
{return a<b?a:b;}

It's clunky and cumbersome, and you need to have foreknowledge about SFINAE techniques to understand why someone would ever write something like that. It's extremely expert friendly. Templates already have that power, but that is an historical coincidence. Concepts (lite) and constraints give the ability to express the same thing in a much more natural way.

Compare the above with your OP or this:

template<LessCompareable T>
const T& comp(const T& a , const T& b)
{return a<b?a:b;}

Which of the alternatives expresses things clearer? Not the old technique, I'd say.

like image 180
StoryTeller - Unslander Monica Avatar answered Nov 05 '22 12:11

StoryTeller - Unslander Monica


One important feature of concept in contrast to existing methods is shrinking the compile errors to definition time and instantiation time. Currently all the errors are generated at the instantiation of the template and it is hard to detect whether the template definition is ill-formed and never compiles or prepared parameters are inappropriate. Main goal of concept is to separate the two types of errors.

like image 1
Red.Wave Avatar answered Nov 05 '22 14:11

Red.Wave