İlginç soru. Son zamanlarda Andrew Sutton'ın Kavramlar hakkındaki konuşmasını izledim ve Soru-Cevap oturumunda birisi aşağıdaki soruyu sordu (aşağıdaki bağlantıda zaman damgası):
CppCon 2018: Andrew Sutton “60 Kavramlar: Bilmeniz gereken her şey ve bilmediğiniz hiçbir şey”
Yani soru şu şekilde kayboluyor: If I have a concept that says A && B && C, another says C && B && A, would those be equivalent?
Andrew evet yanıtı verdi, ancak derleyicinin kavramları atomik mantıksal önermelere ( atomic constraints
Andrew terimi yazdığı gibi ) ayrıştırmak için bazı iç yöntemlere (kullanıcıya şeffaf) sahip olduğuna dikkat çekti ve eşdeğer.
Şimdi cppreference'in ne dediğine bakın std::same_as
:
std::same_as<T, U>
ını kapsamaktadır std::same_as<U, T>
ve tersi de doğrudur.
Bu temelde bir "sadece-ve-eğer-sadece-" ilişkisidir: birbirlerini ima ederler. (Mantıksal Eşdeğerlik)
Benim tahminim burada atom kısıtlamaları std::is_same_v<T, U>
. Yolu derleyiciler tedavi std::is_same_v
onları düşünmek neden olabilir std::is_same_v<T, U>
ve std::is_same_v<U, T>
iki farklı kısıtlamaları olarak (bunlar farklı varlıklardır!). Yani std::same_as
bunlardan sadece birini kullanarak uygularsanız :
template< class T, class U >
concept same_as = detail::SameHelper<T, U>;
Sonra std::same_as<T, U>
ve std::same_as<U, T>
farklı atom kısıtlamayla karşı "patlayabilir" ve dengi değil olacaktı.
Derleyici neden umursuyor?
Bu örneği düşünün :
#include <type_traits>
#include <iostream>
#include <concepts>
template< class T, class U >
concept SameHelper = std::is_same_v<T, U>;
template< class T, class U >
concept my_same_as = SameHelper<T, U>;
// template< class T, class U >
// concept my_same_as = SameHelper<T, U> && SameHelper<U, T>;
template< class T, class U> requires my_same_as<U, T>
void foo(T a, U b) {
std::cout << "Not integral" << std::endl;
}
template< class T, class U> requires (my_same_as<T, U> && std::integral<T>)
void foo(T a, U b) {
std::cout << "Integral" << std::endl;
}
int main() {
foo(1, 2);
return 0;
}
İdeal olarak, my_same_as<T, U> && std::integral<T>
toplamlar my_same_as<U, T>
; bu nedenle, derleyici ikinci şablon uzmanlığını seçmelidir, ancak ... değil: derleyici bir hata yayar error: call of overloaded 'foo(int, int)' is ambiguous
.
Bunun arkasındaki sebep beri olmasıdır my_same_as<U, T>
ve my_same_as<T, U>
birbirlerini subsume gelmezmy_same_as<T, U> && std::integral<T>
ve my_same_as<U, T>
(boyunduruk ilişkisi altında kısıtlamaları kısmen sıralı sette) eşsiz hale gelir.
Ancak,
template< class T, class U >
concept my_same_as = SameHelper<T, U>;
ile
template< class T, class U >
concept my_same_as = SameHelper<T, U> && SameHelper<U, T>;
Kod derlenir.
SameHelper<T, U>
Doğru olması, olabileceği anlamına gelmezSameHelper<U, T>
.