sınıf uzmanlığında clang / gcc tutarsızlığı


9

Ben yapılandırılmış bağlama için C ++ 17 özel bir sınıf tuple_size/ uzmanlaşmaya çalışırken bu sorunla karşılaştım tuple_element.

Aşağıdaki kod GCC'de derlenir, ancak clang'da değil (her iki gövde sürümü, aşağıdaki bağlantıya bakın).

#include <type_traits>

template<typename T, typename... Ts>
using sfinae_t = T;

template<typename T, bool... Bs>
using sfinae_v_t = sfinae_t<T, typename std::enable_if<Bs>::type...>;

template <typename T>
struct Test;

template <typename T>
struct Test<sfinae_v_t<T, std::is_integral_v<T>>> {};

void f() {
    Test<int> t;
}

https://godbolt.org/z/ztuRSq

Clang tarafından sağlanan hata budur:

<source>:13:8: error: class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list

struct Test<sfinae_v_t<T, std::is_integral<T>::value>> {};

       ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1 error generated.

Compiler returned: 1

Bu derleyici bir hata mı yoksa yukarıdaki kod bazı UB çağırıyor mu?


3
Bu basitleştirilmiş olabilir hatta daha .
Evg

3
ICC ve MSVC'nin her ikisi de derlenemez.
ChrisMM

@Evg O en şaşırtıcı olduğunu gccbunun gibi görerek derleme değil, derler bu ...
Max Langhof

1
Ben (yani aynı nedenle tamamen yanılmıyorsam FWIW bu kötü şekillendirilmiş olmalıdır bu kötü oluşturulur).
Max Langhof

1
standart teklif ettiğimiz için, dil-avukat etiketini ekledim.
Guillaume Racicot

Yanıtlar:


3

Aşağıda söylediğim ( ESKİ POST altında ) bir dereceye kadar doğru olmalı, ancak bununla ilgili asıl sorun, SFINAE'nin yanlış kullanılmasıdır, bu yüzden artık bunun gcc'de bir hata olduğundan emin değilim.

Bir takma ad bildirimi her zaman başarılı olmalıdır, orada bir sınıf veya işlev bildirimi veya uzmanlık (takma adları uzmanlaştıramayacağınız için mantıklı değildir) olmadığı için orada SFINAE yapamazsınız. Takma ad bildirimi başarılı olmazsa, program yanlış biçimlendirilir. Bu nedenle derleyici, takma ad bildiriminin siz böyle bir şablonu somutlaştırmaya zorlayana kadar başarılı olamayacağını varsayabilir.

Bu nedenle, derleyicinin sfinae_v_t<T,...>her zaman olduğunu düşünmesi mükemmel bir şekilde kabul edilebilir T, çünkü bu program yanlış biçimlendirilmediğinde gerçekleşecektir. Bu nedenle, programın kötü biçimlendirilmediği tüm durumlarda, kısmi uzmanlaşmanın uzmanlaşmadığını ve bu nedenle bunun kötü biçimlendirildiğini size söyleyecektir. (Clang bunu yapar).

Derleyicinin bunu yapmaya zorlandığını sanmıyorum. Ve eğer öyle değilse ve sadece "Tamam, sfinae_v_tbir çeşit, her neyse " diye düşünüyorsa , o zaman bu bir yeniden açıklama olduğu açık değildir. Bence bunlardan birini başlatana kadar hata atmamakta yanlış olan bir şey yok.

Ancak bunu başlattığımızda, ya bir yeniden açıklama yapmamız ya std::enable_ifda şablon argümanına bağlı olarak programın kötü biçimlendirilmiş olması sorunu olmalıdır . GCC bunlardan en az birini almalı ama hiçbirini almıyor.

Bu aynı zamanda daha kolay örnek için kesinlikle geçerli değildir std::enable_if. Bu yüzden hala bunun GCC'de bir hata olduğunu düşünüyorum, ancak artık kesin olarak söyleyemediğim kadar aklımda kaldı. Sadece söyleyebilirim, birisi bunu bir hata olarak rapor etmeli ve gcc'den insanların bunu düşünmesine izin vermelidir.

ESKİ POST

Bu gcc'de bir hata. Standart bize işlev şablonlarında bir sınıf şablonunu dönüştürme kuralları verir . Bir sınıf şablonu, işlevi kısmi işlev şablonu sıralamasında diğerinin önüne gelirse diğerinden daha uzmanlaşmıştır.

Burada fonksiyonları oluşturdum ve şimdi gcc onları çağırmanın belirsiz olduğunu iddia ediyor, bu nedenle sınıf şablonlarının eşit olarak belirtildiğini de söylemek zorundayım.

Not: Standardı dikkatle okurken, kafamdaki derleyici clang ile aynı fikirde.


Are sfinae_v_t<T, std::is_integral_v<T>>ve sfinae_v_t<T, !std::is_integral_v<T>>aynı tipler olarak ele? Anlamsal olarak, değiller.
ofo

@GuillaumeRacicot Muhtemelen, ama tam olarak nedenini anlamak istiyorum. Örneğin standart da diyor "Bağımlı isimler kısmi uzmanlaşma bildirirken kontrol edilemez, ancak kısmi uzmanlaşma içine yerleştirirken kontrol edilecektir." Farketmez aynı tip yana kısmen uzmanlık T ikame sonra karar verilmesi için olan ortalama olmadığının sfinae_v_t<T>bağlıdır T? Bu durumda, aynı olmazlar çünkü her ikisi de kötü biçimlenir.
ofo

@ofo söylemeliyim, emin değilim. Bunlardan biri asla bir tür olmayacağından ve her ikisini de şablon olmayan bir bağlamda kullanmak nedeniyle derleme hatasına neden olacağından, bu ikisi hakkında düşünmek bile bir fikirdir enable_if_t. Standardı en iyi okuduğum şey, aynı olup olmadıkları önemli değil. Kısmi sıralama için, her zaman bir fonksiyonun templare parametre formunu diğerinin şablon argüman formuyla (yani intzaten ikame edilir) karşılaştırırız ve sonra bunlardan birinde gerçek bir tip vardır, bu yüzden karşılaştırmamız gerekmez onları soyut.
n314159

1
Derin kazı buldum bu gelen burada . SFINAE şablon takma adlarıyla iyi çalışmalıdır, aksi takdirde template<bool B, typename T> enable_if_t = typename enable_if<B, T>::type;çalışmaz. Ben devam ve gcc karşı hata dosya, ama gerçekten orada gcc yanlış emin değilim. Teşekkürler.
ofo
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.