Same_as konsepti tip eşitliğini neden iki kez kontrol ediyor?


19

Https://en.cppreference.com/w/cpp/concepts/same_as adresinde same_as konseptinin olası uygulanışına baktığımda garip bir şey olduğunu fark ettim.

namespace detail {
    template< class T, class U >
    concept SameHelper = std::is_same_v<T, U>;
}

template< class T, class U >
concept same_as = detail::SameHelper<T, U> && detail::SameHelper<U, T>;

İlk soru, bir SameHelperkavramın neden açıklandığıdır? İkinci neden same_asise çek Taynıdır Uve Uaynı T? Gereksiz değil mi?


SameHelper<T, U>Doğru olması, olabileceği anlamına gelmez SameHelper<U, T>.
Bazı programcı dostum

1
mesele bu, eğer b eşittir b, b eşittir değil mi?
user7769147

@ user7769147 Evet, ve bu ilişkiyi tanımlıyor.
François Andrieux

4
Hmm, std :: is_same dokümantasyonunda " Değişebilirlik tatmin edici, yani herhangi bir iki T ve U tipi için, is_same<T, U>::value == trueeğer ve sadece, is_same<U, T>::value == true" diyor. Bu, bu çifte kontrolün gerekli olmadığı anlamına gelir
Kevin

1
Hayır, bu yanlıştır, std :: is_same diyor ki: ancak koşul geçerliyse, iki tür değişmeli. Çok lazım değil. Fakat değişmeli olmayan iki türün örneğini bulamıyorum.
Nemanja Boric

Yanıtlar:


16

İ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 constraintsAndrew 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_vonları 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_asbunlardan 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.


same_as <T, U> ve same_as <U, T> da farklı atomik kontrendikasyonlar olabilir, ancak sonuçları yine aynı olacaktır. Derleyici aynı_as'ı mantıksal açıdan aynı olan iki farklı atomik kısıt olarak tanımlamaya neden bu kadar önem veriyor?
user7769147

2
Derleyicinin herhangi iki ifadeyi kısıtlama toplamı için ayrı olarak düşünmesi gerekir , ancak kendilerine karşı argümanları bariz bir şekilde düşünebilir . Yani sadece biz (o hangi kısıtlamaları karşılaştırırken onlar İsminin sipariş önemli değil böylece), aşağıdakiler de gereklidir iki yönde gerekiyor değil iki yapar: kullanımlarını ait aynı ifadede türemiştir. SameHelperis_same_v
Davis Herring

@ user7769147 Güncellenmiş cevaba bakın.
Rin Kaenbyou

1
Kavramsal eşitlik konusunda geleneksel bilgelik yanlış görünüyor. is_same<T, U>Aynı olan şablonlardan farklı is_same<U, T>olarak, aynı ifadeden oluşturulmadıkları sürece iki atom kısıtlaması aynı kabul edilmez. Dolayısıyla her ikisine de ihtiyaç vardır.
AndyG

Ne olmuş are_same_as? template<typename T, typename U0, typename... Un> concept are_same_as = SameAs<T, U0> && (SameAs<T, Un> && ...);bazı durumlarda başarısız olur. Örneğinare_same_as<T, U, int>are_same_as<T, int, U>are_same_as<U, T, int>
user7769147

2

std::is_same yalnızca aşağıdaki durumlarda true olarak tanımlanır:

T ve U aynı cv nitelikleri ile aynı türü adlandırır

Bildiğim kadarıyla, standart "aynı tip" in anlamını tanımlamaz, ama doğal dilde ve mantıkta "aynı" bir denklik ilişkisidir ve dolayısıyla değişmeli olur.

Atfettiğim bu varsayım göz önüne alındığında, is_same_v<T, U> && is_same_v<U, V>gerçekten gereksiz olurdu. Ancak same_­as,is_same_v ; bu sadece teşhir amaçlıdır.

Her ikisi için de açık çek için uygulanması için izin verir same-as-impltatmin etmeksame_­as değişmeli olmadan olmasını sağlar. Bu şekilde belirtilmesi, kavramın nasıl uygulanabileceğini kısıtlamadan tam olarak nasıl davrandığını açıklar.

Tam olarak bu yaklaşımın neden belirtmek yerine seçildiğini is_same_vbilmiyorum. Seçilen yaklaşımın bir avantajı, iki tanımın birbirinden ayrılmasıdır. Biri diğerine bağlı değildir.


2
Sana katılıyorum, ama bu son argüman biraz gergin. Bana öyle geliyor ki: "Hey, bana iki türün aynı olup olmadığını söyleyen bu yeniden kullanılabilir bileşene sahibim. Şimdi, türlerin aynı olup olmadığını bilmesi gereken başka bir bileşene sahibim, ancak önceki bileşenimi yeniden kullanmak yerine , Ben sadece bu duruma özgü geçici bir çözüm yaratacağım. Şimdi eşitlik tanımına ihtiyaç duyan adamı eşitlik tanımına sahip olandan ayırdım.
Cássio Renan

1
@ CássioRenan Tabii. Söylediğim gibi, nedenini bilmiyorum, bu sadece gelebileceğim en iyi akıl yürütme. Yazarların daha iyi bir mantığı olabilir.
eerorika
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.