Soru C ++ vs D, Ada ve Eiffel (şablonlarla korkunç hata mesajları)


C ++ problemlerinden biri, şablonları ve şablon meta programlamasını yoğun olarak kullanan koddan aldığımız korkunç hata mesajlarıdır. Kavramlar bu sorunu çözmek için tasarlandı, ancak maalesef bir sonraki standartta olmayacaklar.

Merak ediyorum, bu problem jenerik programlamayı destekleyen tüm diller için ortak mıdır? Ya da C ++ şablonları ile bir şeyler yanlış mı?

Ne yazık ki, başka bir dil bilmiyorum, bu genel bir programlamayı destekliyor (Java ve C # jenerikler çok basitleştirilmiş ve C ++ şablonları kadar güçlü değil).

Ben de size soruyorum: D, Ada, Eiffel şablonları (jenerikler) de böyle çirkin hata mesajları üretiyorlar mı? Ve güçlü genel programlama paradigmasıyla, ancak çirkin hata mesajları olmadan dil sahibi olmak mümkün mü? Ve eğer evet ise, bu dillerin bu sorunu nasıl çözdüğü?

Düzenle: downvoters için. C ++ ve şablonları çok seviyorum. Şablonların kötü olduğunu söylemiyorum. Aslında generic programlama ve şablon meta programlamasının büyük bir hayranıyım. Sadece derleyicilerden neden bu kadar çirkin hata mesajı alıyorum diye soruyorum.


25
2018-04-03 11:27


Menşei


TMP herhangi bir şekilde planlanmışsa C ++ güzel hata mesajlarına sahip olur. 'Hata' ile dile çevrildiğini söyleyebilirsin. - Xeo
STL Hata Mesajı Decryptor. Acıyı daha çok gider. - Mat
@Mat: Eğer sadece aktif gelişme durmamış olsaydı. :( VC9'a geri dönmeyeceğim, bilirsin. - Xeo
Eğer bir derleyici böyle mesajlar veriyorsa, derhal Dundich, fakat tüm derleyiciler bu tür bir hata mesajı veriyorsa, dilde bir şeylerin yanlış olduğu anlamına gelir. C ++ 'ya kavram eklemenin başlıca nedenlerinden biri, derleyicinin daha net hata mesajları üretmesine yardımcı olmaktır. - UmmaGumma
@Serge Dundich: Comeau C ++, Greg Comeau tarafından tasarlanmıştır. Standart yazarlar birçok şirketten farklı bir gruptur. - MSalters


Cevaplar:


Sorun şu ki, bağlamda ne olursa olsun, hataların düzeltilmesi zordur.

Ve C ve C ++ horri gramerlerini hesaba kattığınızda, sadece hata mesajlarının bundan daha kötü olmadığını düşünebilirsiniz! C dilbilgisinin bir dilbilgisinin temel özellikleri hakkında bir ipucu olmayan insanlar tarafından tasarlandığından korkuyorum; bunlardan biri, daha iyi bir bağlam ve daha iyi olan diğer bir varlıktır. mümkün olduğu kadar açık.

Ortak bir hatayı gösterelim: bir yarı kolonun unutulması.

struct CType {
  int a;
  char b;
}
foo
bar() { /**/ }

Tamam, bu yanlış, eksik yarım kolon nereye gitmeli? Maalesef belirsiz, önce ya da sonra gidebilir foo Çünkü:

  • C, tanımladıktan sonra adımda bir değişkeni beyan etmenin normal olduğunu düşünür. struct
  • C, bir işlev için bir dönüş türü belirtmemek normaldir (bu durumda varsayılan olarak int)

Sebep edersek, şunu görebiliriz:

  • Eğer foo bir türü isimlendirir, daha sonra işlev bildirgesine aittir
  • eğer değilse, muhtemelen bir değişkeni ifade eder ... tabii ki bir yazım hatası yaptık ve yazılması gerekiyordu fooltüründe olan: /

Gördüğünüz gibi, hataların düzeltilmesi düpedüz zordur, çünkü yazarın ne anlama geldiğini anlamalıyız ve dilbilgisi alıcı olmaktan uzaktır. Yine de imkansız değildir ve çoğu hata aslında daha fazla ya da daha az doğru teşhis edilebilir ve hatta daha da düzelebilir. önemli çaba.

Üzerinde çalışan insanlar gibi görünüyor gcc üretimle daha çok ilgileniyorlar hızlı kodu (ve hızlı, gcc 4.6 en son kriterleri aramak) ve ilginç özellikleri (gcc zaten herkesin - C ++ 0x) en çok uygulamak hata mesajlarını okumaktan daha kolay üretiyor. Onları suçlayabilir misin? Yapamam.

Neyse ki, doğru hata raporlaması ve iyi bir hata düzeltmesinin çok değerli bir amaç olduğunu düşünen insanlar var ve bunlardan bazıları CLang üzerinde biraz çalışıyor ve bunu yapmaya devam ediyorlar.

Başımın üst kısmındaki bazı güzel özellikler:

  • Tersi, tam olarak hata kaynağının nereden kaynaklandığını göstermek için kaynak aralıkları içeren tam hata iletileri
  • Düzelt ne anlama geldiğini anlatan notlar
  • Böyle bir durumda, derleyici dosyanın geri kalanını sanki sabitleme çizgileri üzerine çizgiler sermek yerine, zaten orada olmuş gibi ayrıştırır.
  • (son zamanlarda) notlar için dahil olmak üzere yığın yığını dahil olmaktan kaçının.
  • (son zamanlarda) yalnızca geliştiricinin yazdığı şablon parametre türlerini açığa çıkarmaya ve yazım hatalarını korumaya çalışarak std::vector<Name> yerine std::vector<std::basic_string<char, std::allocator<char>>, std::allocator<std::basic_string<char, std::allocator<char>> > tüm fark yaratan)
  • (yeni) bir kayıp durumunda doğru şekilde iyileşme template başka bir şablon yönteminden bir şablon yöntemine çağrıda eksik olması durumunda

Ama bunların her biri birkaç tane gerekli saatler için günler işin.

Kesinlikle bedava gelmediler.

Şimdi, kavramlar (normalde) hayatımızı kolaylaştırmış olmalıdır. Fakat çoğunlukla test edilmemişlerdi ve bu yüzden onları taslaktan çıkarmak tercih edildi. Bunun için memnun olduğumu söylemeliyim. C ++ göreceli atalet göz önüne alındığında, iyice gözden geçirilmemiş olan özellikleri dahil etmemek daha iyidir ve konsept haritaları beni gerçekten heyecanlandırmadı. Ne de Bjarne ya da Herb'i heyecanlandırdılar, çünkü bir sonraki standart için Kavramları yeniden düşüneceklerini söylediler.


15
2018-04-03 15:16



"C, bir işlev için bir dönüş türü belirtmemek normaldir (bu durumda, varsayılan olarak int)." Ancak C ++, bu dilbilgisine kesinlikle izin vermez ve soru C ++ ile ilgili olarak, kesinlikle bunu düzenlerdim. - Puppy
@DeadMG: C ++ 'da (şablonların dışında) belirsizliğin iyi bir örneğini düşünemedim, bu yüzden şimdi onu böyle bırakacağım :) Eğer kendiniz bir tane varsa, cevabı düzenleyin, umurumda değil. - Matthieu M.
Çok daha kötü C ++ özgü belirsizlikler var. Örneğin. tarafından bildirilen SomeType Foo(abcd); sözdiziminden çıkarılamaz. Sadece çevre doğru cevabı verir: eğer abcd sonra tür adı Foo bir fonksiyon alıyor abcdgeri dönüşlü argüman SomeType ve eğer abcd nesne adı ise Foo nesnenin türü SomeType ile başlatıldı abcd değer. Bu uzun bir süre G ++ geliştiricileri için önemli bir sorundu. Ve diğer tip-isim ve nesne adı problemleri çok. Neyse mesajınız harika. +1 - Serge Dundich
A*B = D+E;: Eğer A bir türüdür, bu bir yavaşlamadır. Eğer A aşırı yükler bir değişkendir operator* yükler atama üzerinde bir şey dönmek için, bu bir ifade değerlendirme. - BCS
@Serge, @BCS: Evet, bunlar belirsizdir, ancak derleyicinin neden bazen yararsız mesajlar sunabileceğini göstermek için bir hata (burada unutulmuş bir yarı-kolon) varlığında bir belirsizlik arıyordum. Yine de örnekler için teşekkürler, sorunu dilbilgisinin kendisi ile güzelce gösterirler. - Matthieu M.


Genel olarak, generics için Ada derleyicisi hata mesajlarını, diğer tüm Ada derleyici hata mesajlarından çok daha fazla okunması zor buldum.

Öte yandan C ++ şablon hata mesajları, hata romanlar. Benim düşündüğüm en önemli fark, C ++ 'nın şablon örneği olmasının yoludur. Şey, C ++ şablonları Ada jeneriklerinden çok daha esnektir. Çok esnek, neredeyse bir makro ön işlemciye benziyor. Boost'daki zeki insanlar bunu lambdalar ve hatta tüm diğer diller gibi şeyleri uygulamak için kullandılar.

Bu esneklik nedeniyle, şablon hiyerarşisinin tamamı, şablon parametrelerinin belirli bir şekilde ilk kez karşılaştığı her defasında yeniden derlenmelidir. Böylelikle, uyumsuzlukları gidermek için birkaç API'nin aşağı katmanı, zayıf API istemcisine deşifre edilmek üzere sunulacaktır.

Ada'da, Generics aslında güçlü bir şekilde yazılmıştır ve normal paketler ve alt programlar gibi istemciye gizlenen tüm bilgileri sağlar. Yani bir hata mesajı alırsanız, genellikle uygulamak için kullanılan tüm hiyerarşiyi değil, sadece genel olarak denemeye çalıştığınız jeneriği referans alırsınız.

Evet, C ++ şablon hata mesajları Ada'nınkinden daha kötüdür.

şimdi ayıklamatamamen farklı bir hikaye ...


14
2018-04-04 15:52



C ++ şablonları Turing tamamlandı, bu yüzden sadece bir makro ön işlemcisi değil. - naasking


D, şablon hata mesajlarının kalitesini iyileştirmek için iki özelliğe sahiptir: Kısıtlamalar ve static assert.

// Use constraints to only allow a function to operate on random access 
// ranges as defined in std.range.  If something that doesn't satisfy this
// is passed, the compiler will error before even trying to instantiate
// fun().
void fun(R)(R range) if(isRandomAccessRange!(R)) {
    // Do stuff.
}


// Use static assert to check a high level invariant.  If 
// the predicate is false, the error message will be 
// printed and compilation will stop before a screen 
// worth of more confusing errors are encountered.
// This function takes any number of ranges to merge sort
// and the same number of temporary buffers to merge into.
void mergeSort(R...)(R ranges) {
    static assert(R.length % 2 == 0, 
        "Must have equal number of ranges to be sorted and temporary buffers.");

    static assert(allSatisfy!(isRandomAccessRange, R), 
        "All arguments to mergeSort must be random access ranges.");

    // Implementation
}

9
2018-04-03 14:26



ilginç görün. Yani D böyle bir sorun yaşamaz mı? Ve D'nin hataları her zaman açıktır? - UmmaGumma
C ++ 0x var static_assertBöylece, sadece 2. bölüm artık D'yi daha iyi yapmaz. Ama derleme zamanı dize işleme ile birleştirildi, D static assertHata raporlama özelliği çok daha üstündür (örn. q{a**b} ve int içinde ideone.com/TQ6wY C ++ içinde 0x). - kennytm
@Ashot: D iyi yazılmış şablonlar verilen bu sorundan muzdarip değil. Hala hızlı ve kirli şablonlar veriyor. - dsimcha


Makale Genel Programlama dahil olmak üzere birçok dilde jeneriklerin artılarını ve eksilerini özetlemektedir. Ada özellikle. Şablon uzmanlığı eksik olsa da, hepsi Ada genel  örnekleri "örnek bildirime eşdeğerdir… hemen ardından örnek gövde". Pratik bir mesele olarak, hata mesajları derleme zamanında meydana gelme eğilimindedir ve tipik olarak tür güvenliğinin bilinen ihlallerini temsil ederler.


8
2018-04-03 20:27



Ek olarak, Ada kaynak kodunun okunması daha kolaydır. Bu daha okunabilir hata mesajlarına yol açar. - oenone


Eyfel, tüm hata mesajlarının en iyisine sahiptir çünkü tüm şablon sistemlerinin en iyisi vardır. Bu dil ile tamamen entegredir ve iyi çalışır çünkü argümanlarda covarianz kullanan tek dildir.

Bu nedenle daha sonra basit bir derleyici kopyalayıp yapıştırın. Ne yazık ki, birkaç satırdaki farkı açıklamak imkansız. Sadece git ve EiffelStudio'ya bir bak.


4
2018-04-20 00:52





Hata mesajlarını iyileştirmek için bazı çabalar vardır. çınlamaÖrneğin, daha kolay okunabilir derleyici hata iletileri oluşturmaya oldukça fazla önem vermiştir. Kısa bir süredir bunu kullanıyorum ama şu ana kadarki deneyimim GCC'nin eşdeğer hatalarına kıyasla oldukça olumlu geçti.


2
2018-04-03 11:56