Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the rules for ordering concept constrained functions in C++20?

I just learned that C++ concepts are much more superior than SFINAE because functions constrained by concepts are ordered, meaning a more constrained function is considered a better match than a less constrained one.

How exactly are the rules used by the compiler to estimate how much constrained a function is? How do these rules interact with conventional overload resolution when mixing non-restrained and restrained overloads?

like image 594
Silicomancer Avatar asked Nov 07 '22 07:11

Silicomancer


1 Answers

To make simple..., during the overload resolution process:

First, all functions that would be viable without the constraints but whose constraint are not satisfied are considered not viable.

So the set of viable overload contains functions, template functions and constrained templated function with satisfied constraints.

Then the best overload is chosen, during the first step without considering constraints. At each of these steps, the compiler compare 2 candidates if one appears to be better than the other, this candidate is considered to be a better match than the other, without considering any further criterium:

  1. It first considers argument conversion
  2. then, if one is a template and the other is not, it chooses the non template one
  3. At this step, there are necessarily 2 templates. It considers if one is more specialized than the other (constraints does not play any role here)
  4. It considers if one of the template is more constrained than the other.

For example:

template <Concept1 T> foo(T&&);
template <Concept2 T> foo(const T&);
template <Concept3 T> foo(const T&);

 void g(){
    int i=10;
    const int& j =i;

    foo (j) // the compiler will check the 2 last foo 
            //to see if one is more constrained than the other
    foo (i) //the first foo is selected even if the second or third foo could look like they are more constrained
    }

A template T1 is more constrained than a template T2 if the compiler can prove that, for any possible set of template arguments, if the constraint of T1 is satisfied then the constraint of T2 is satisfied. It check if it can prove:

constraints of T1 statisfied  ==>  constraints of T2 satisfied

where ==> means imply.

To do such a demonstration, the compiler is quite limited. It will only use a subset of boolean algebra (only and and or operations) where the operand are a decomposition of constraints and concept into so-called atomic constraints. To simplify atomic constraints are the operands of none folded "logical and expressions" and "logical or expressions" that appear within constraints and concept definitions.

I suppose that trying to go further would result in copying the standard. So here is a link to the most pertinent standard section [temp.constr]

like image 60
Oliv Avatar answered Nov 14 '22 23:11

Oliv