C ++ 20 có một cơ chế để quyết định khi một thực thể bị ràng buộc cụ thể nào "bị ràng buộc" hơn một thực thể khác. Đây không phải là một điều đơn giản.
Điều này bắt đầu với khái niệm phá vỡ một ràng buộc thành các thành phần nguyên tử của nó, một quá trình gọi là chuẩn hóa ràng buộc . Nó lớn và quá phức tạp để đi vào đây, nhưng ý tưởng cơ bản là mỗi biểu thức trong một ràng buộc được chia thành các phần khái niệm nguyên tử của nó, theo cách đệ quy, cho đến khi bạn đạt đến một biểu thức phụ thành phần không phải là một khái niệm.
Vì vậy, hãy xem xét cách integral
và các signed_integral
khái niệm được định nghĩa :
template<class T>
concept integral = is_integral_v<T>;
template<class T>
concept signed_integral = integral<T> && is_signed_v<T>;
Sự phân rã của integral
chỉ là is_integral_v
. Sự phân hủy của signed_integral
là is_integral_v && is_signed_v
.
Bây giờ, chúng ta đến với khái niệm về hạn chế hạn chế . Điều này khá phức tạp, nhưng ý tưởng cơ bản là một ràng buộc C1 được cho là "tạo ra" một ràng buộc C2 nếu sự phân tách của C1 chứa mọi biểu thức con trong C2. Chúng ta có thể thấy rằng integral
không bao hàm signed_integral
, nhưng signed_integral
không bao hàm integral
, vì nó chứa tất cả những gì integral
không.
Tiếp theo, chúng ta đến để đặt hàng các thực thể bị ràng buộc:
Một khai báo D1 ít nhất là bị ràng buộc như một khai báo D2 nếu * D1 và D2 đều là các khai báo bị ràng buộc và các ràng buộc liên quan của D1 bao gồm các khai báo của D2; hoặc * D2 không có ràng buộc liên quan.
Bởi vì các khoản signed_integral
phụ integral
, <signed_integral> wrapper
"ít nhất là bị ràng buộc" như <integral> wrapper
. Tuy nhiên, điều ngược lại là không đúng sự thật, do sự sụt giảm không thể đảo ngược.
Do đó, theo quy tắc cho các thực thể "ràng buộc hơn":
Một khai báo D1 bị ràng buộc nhiều hơn một khai báo D2 khác khi D1 ít nhất bị ràng buộc như D2 và D2 ít nhất không bị ràng buộc như D1.
Vì <integral> wrapper
ít nhất là không bị ràng buộc như <signed_integral> wrapper
, cái sau được coi là hạn chế hơn cái trước.
Và do đó, khi cả hai có thể áp dụng, tuyên bố ràng buộc hơn sẽ thắng.
Xin lưu ý rằng các quy tắc hạn chế ràng buộc dừng khi gặp một biểu thức không phải là a concept
. Vì vậy, nếu bạn đã làm điều này:
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>;
Trong trường hợp này, my_signed_integral
sẽ không bao gồm std::integral
. Mặc dù my_is_integral_v
được định nghĩa giống hệt nhau std::is_integral_v
, bởi vì đó không phải là một khái niệm, các quy tắc phụ của C ++ không thể nhìn xuyên qua nó để xác định rằng chúng giống nhau.
Vì vậy, các quy tắc tiêu thụ khuyến khích bạn xây dựng các khái niệm ngoài hoạt động trên các khái niệm nguyên tử.