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 integrale :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 integralnon mlo signed_integral, ma signed_integral lo fa subsume integral, in quanto contiene tutto ciò integralfa.
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_integralsussume 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> wrappernon è 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.