C ++ 20 ha un meccanismo per decidere quando una particolare entità vincolata è "più vincolata" di un'altra. Questa non è una cosa semplice
Questo inizia con il concetto di scomporre un vincolo nei suoi componenti atomici, un processo chiamato normalizzazione dei vincoli . È grande e troppo complesso per entrare qui, ma l'idea di base è che ogni espressione in un vincolo è suddivisa in pezzi concettuali atomici, ricorsivamente, fino a raggiungere una sottoespressione componente che non è un concetto.
Detto questo, diamo un'occhiata a come sono definiti i concetti integral
e :signed_integral
template<class T>
concept integral = is_integral_v<T>;
template<class T>
concept signed_integral = integral<T> && is_signed_v<T>;
La decomposizione di integral
è giusta is_integral_v
. La decomposizione di signed_integral
è is_integral_v && is_signed_v
.
Veniamo ora al concetto di sussunzione di vincoli . È un po 'complicato, ma l'idea di base è che si dice che un vincolo C1 "sussume" un vincolo C2 se la decomposizione di C1 contiene ogni sottoespressione in C2. Possiamo vedere che integral
non mlo signed_integral
, ma signed_integral
lo fa subsume integral
, in quanto contiene tutto ciò integral
fa.
Successivamente, arriviamo all'ordinamento di entità vincolate:
Una dichiarazione D1 è vincolata almeno quanto una dichiarazione D2 se * D1 e D2 sono entrambe dichiarazioni vincolate e i vincoli associati di D1 sono inferiori a quelli di D2; o * D2 non ha vincoli associati.
Perché signed_integral
sussume integral
, <signed_integral> wrapper
è "almeno vincolato" come <integral> wrapper
. Tuttavia, non è vero il contrario, poiché la sussunzione non è reversibile.
Pertanto, in accordo con la regola per le entità "più vincolate":
Una dichiarazione D1 è più vincolata di un'altra dichiarazione D2 quando D1 è vincolata almeno come D2 e D2 non è vincolata almeno come D1.
Poiché il <integral> wrapper
non è almeno vincolato come <signed_integral> wrapper
, quest'ultimo è considerato più vincolato del primo.
E quindi, quando entrambi potrebbero applicarsi, vince la dichiarazione più vincolata.
Tenere presente che le regole della sottosezione di vincolo si interrompono quando si incontra un'espressione che non è a concept
. Quindi se hai fatto questo:
template<typename T>
constexpr bool my_is_integral_v = std::is_integral_v<T>;
template<typename T>
concept my_signed_integral = my_is_integral_v<T> && std::is_signed_v<T>;
In questo caso, my_signed_integral
non si riassumerebbe std::integral
. Anche se my_is_integral_v
è definito in modo identico std::is_integral_v
, poiché non è un concetto, le regole di assunzione di C ++ non possono scrutare attraverso di esso per determinare che sono uguali.
Quindi le regole di sussunzione ti incoraggiano a costruire concetti fuori dalle operazioni su concetti atomici.