Kullanıcı tanımlı değişmez değerler C ++ 'a hangi yeni özellikleri ekler?


139

C ++ 11 tanıtır kullanıcı tanımlı değişmezleri (mevcut değişmezleri dayalı yeni hazır sözdizimi giriş sağlayacak int, hex, string,float ), böylece her türlü değişmez bir sunum için mümkün olacaktır.

Örnekler:

// imaginary numbers
std::complex<long double> operator "" _i(long double d) // cooked form
{ 
    return std::complex<long double>(0, d); 
}
auto val = 3.14_i; // val = complex<long double>(0, 3.14)

// binary values
int operator "" _B(const char*); // raw form
int answer = 101010_B; // answer = 42

// std::string
std::string operator "" _s(const char* str, size_t /*length*/) 
{ 
    return std::string(str); 
}

auto hi = "hello"_s + " world"; // + works, "hello"_s is a string not a pointer

// units
assert(1_kg == 2.2_lb); // give or take 0.00462262 pounds

İlk bakışta bu çok havalı görünüyor ama bunun ne kadar geçerli olduğunu merak ediyorum, sonekleri düşünmeyi _ADve _BCtarihler oluşturmayı denediğimde , operatör siparişinden dolayı sorunlu buldum. 1974/01/06_ADönce 1974/01(düz olarak int) ve ancak daha sonra 06_AD( 0sekiz ve daha fazla sebep olmadan yazılması gereken Ağustos ve Eylül aylarının hiçbirini söylemek için). Bu, sözdiziminin 1974-1/6_ADoperatör değerlendirme sırasının çalışabilmesi için çözülebilir , ancak bu sorun olabilir.

Peki sorum şudur ki, bu özelliğin kendini haklı çıkaracağını düşünüyor musunuz? C ++ kodunuzu daha okunabilir kılacak başka hangi değişmez değerleri tanımlamak istersiniz?


Haziran 2011'deki nihai taslağa uyacak şekilde söz dizimi güncellendi


8
Bunu kapatmak için oy vereceğim. Başlık oldukça açıklayıcıdır.
Köpek yavrusu

76
@DeadMG, başlıkla ilgili bir sorununuz varsa onu düzenleyebilirsiniz. 11 upvotes ve 8 sık kullanılan 3 yaşındaki bir soruyu kapatmaya çalışırken biraz komik. (Bu sitedeki görgü kurallarının son 3 yılda değiştiğinden bahsetmiyoruz).
Motti

5
Örneklerinizde bir hata olduğunu düşünüyorum: string operator "" _s(const char*s);"ayrıştırmak için kullanılamaz "hello"_s". Bu bir dize değişmezidir ve ek bir size_tparametreyle operatörü arayacaktır . Haklı mıyım?
towi

1
Merak ettiğim bir şey, C ++ 'da "taşınabilir C" yazmanın uint16_t, davranışları uygulamaya bağlı, benzer türlerle uwrap16ve unum16davranışları uygulamadan bağımsız olacak türlerin yerine uwrap16 w=1; unum16 n=1;, ifadeler w-2ve n-2doğuracak (uwrap16)65535ve (int)-1sırasıyla [ uint16_tsistemlerde ilk sonuç vermez int16 bittir ve sistemlerde, ikinci yerde intbüyük]. Gördüğüm en büyük sorun sayısal değişmezleri ele almaktı.
supercat

1
Sayısal değişmezlerin diğer tanımlanmış davranışlı sayısal türlerle sorunsuz bir şekilde birlikte çalışabilmesi, bu tür türlerin, uygulamaya bağımlı eylemler gerçekleştirmek isteyen kodun uygulamaya güvenmek zorunda kalmadan yapabileceği bir dil oluşturmak için kullanılmasına izin vermesi gibi görünmektedir. tanımlanmış davranışlar. İşaretçi farklılıkları ve sizeofuygulamaya bağlı tamsayı türleri gibi şeyler nedeniyle IDB'nin kaçınılmaz olacağı birkaç yer vardır, ancak durum hala olduğundan çok daha iyi hale getirilebilir. Bu kavram hakkında ne düşünürdünüz?
supercat

Yanıtlar:


71

Aşağıda, yapıcı çağrısı yerine kullanıcı tanımlı değişmez değerleri kullanma avantajının olduğu bir durum vardır:

#include <bitset>
#include <iostream>

template<char... Bits>
  struct checkbits
  {
    static const bool valid = false;
  };

template<char High, char... Bits>
  struct checkbits<High, Bits...>
  {
    static const bool valid = (High == '0' || High == '1')
                   && checkbits<Bits...>::valid;
  };

template<char High>
  struct checkbits<High>
  {
    static const bool valid = (High == '0' || High == '1');
  };

template<char... Bits>
  inline constexpr std::bitset<sizeof...(Bits)>
  operator"" _bits() noexcept
  {
    static_assert(checkbits<Bits...>::valid, "invalid digit in binary string");
    return std::bitset<sizeof...(Bits)>((char []){Bits..., '\0'});
  }

int
main()
{
  auto bits = 0101010101010101010101010101010101010101010101010101010101010101_bits;
  std::cout << bits << std::endl;
  std::cout << "size = " << bits.size() << std::endl;
  std::cout << "count = " << bits.count() << std::endl;
  std::cout << "value = " << bits.to_ullong() << std::endl;

  //  This triggers the static_assert at compile time.
  auto badbits = 2101010101010101010101010101010101010101010101010101010101010101_bits;

  //  This throws at run time.
  std::bitset<64> badbits2("2101010101010101010101010101010101010101010101010101010101010101_bits");
}

Avantajı, çalışma zamanı istisnasının derleme zamanı hatasına dönüştürülmesidir. Bir dize alarak bitset ctor'a statik onay ekleyemezsiniz (en azından dize şablonu bağımsız değişkenleri olmadan).


7
Aynı şeyi std :: bitset'e uygun bir constexpr yapıcısı vererek de yapabilirsiniz.
Nicol Bolas

1
@NicolBolas Haklısın. Aslında orada biri olmadığına şaşırdım. Belki çok geç değilse, 2014 için bir veya iki tane önermeliyiz.
emsr

192

İlk bakışta, basit sözdizimsel şeker gibi görünüyor.

Ancak daha derinlere baktığımızda , C ++ kullanıcı seçeneklerini tam olarak farklı yerleşik türler gibi davranan kullanıcı tanımlı türler oluşturmak için genişlettiği için sözdizimsel şekerden daha fazlası olduğunu görüyoruz . Bu, bu küçük "bonus" C ++ için çok ilginç bir C ++ 11 ekidir.

Gerçekten C ++ ile ihtiyacımız var mı?

Son yıllarda yazdığım kodda birkaç kullanım görüyorum, ancak sadece C ++ ile kullanmadığım için başka bir C ++ geliştiricisi için ilginç olmadığı anlamına gelmiyor .

C ++ (ve C, sanırım), derleyici tanımlı değişmez değerler, tamsayı sayılarını kısa veya uzun tamsayılar, gerçek sayıları float veya double (veya hatta double double) ve karakter dizelerini normal veya geniş chars olarak yazmak için kullandık .

C ++ 'da, potansiyel olarak ek yük olmadan (satır içi, vb.) Kendi türlerimizi (yani sınıflar) yaratma imkanımız oldu . Türlerine operatör ekleme, benzer yerleşik türler gibi davranmalarını sağladık, bu da C ++ geliştiricilerinin dilin kendisine eklenmiş olmaları gibi doğal olarak matrisleri ve karmaşık sayıları kullanmalarını sağlıyor. Döküm operatörleri bile ekleyebiliriz (bu genellikle kötü bir fikirdir, ancak bazen sadece doğru çözümdür).

Kullanıcı türlerinin yerleşik türler gibi davranması için bir şeyi kaçırdık: kullanıcı tanımlı değişmez değerler.

Yani, sanırım bu dil için doğal bir evrim, ama olabildiğince eksiksiz olmak için: " Eğer bir tür oluşturmak istiyorsanız ve onun yerleşik türler kadar mümkün olmasını istiyorsanız, işte araçlar. .. "

Sanırım her ilkel, boolean, integer, vb. Dahil bir yapı yapma kararına çok benziyor ve tüm yapıların Object'den türetilmesini sağlıyor. Bu karar tek başına Java'nın özelliklerine ne kadar boks / kutudan çıkarma korsanlığı olursa olsun, ilkellerle çalışırken .NET'i Java'nın erişiminin çok ötesine taşır.

Gerçekten C ++ ihtiyacınız var mı?

Bu soru SİZİN cevaplamanız içindir. Bjarne Stroustrup değil. Herb Sutter değil. C ++ standart komitesinin herhangi bir üyesi değil. Bu yüzden C ++ seçeneğine sahipsiniz ve kullanışlı bir gösterimi yalnızca yerleşik türlerle sınırlamazlar.

Eğer sen lüzum, o zaman hoş bir ektir. Eğer sen değil, iyi ... kullanmayın. Size hiçbir maliyeti olmayacak.

Özelliklerin isteğe bağlı olduğu C ++ diline hoş geldiniz.

Şişirilmiş ??? Bana komplekslerini göster !!!

Şişirilmiş ve karmaşık (pun amaçlı) arasında bir fark vardır.

Niels tarafından gösterildiği gibi Kullanıcı tanımlı değişmez değerler C ++ 'a hangi yeni özellikleri ekler? , karmaşık bir sayı yazabilmek C ve C ++ 'ya "son zamanlarda" eklenen iki özellikten biridir:

// C89:
MyComplex z1 = { 1, 2 } ;

// C99: You'll note I is a macro, which can lead
// to very interesting situations...
double complex z1 = 1 + 2*I;

// C++:
std::complex<double> z1(1, 2) ;

// C++11: You'll note that "i" won't ever bother
// you elsewhere
std::complex<double> z1 = 1 + 2_i ;

Şimdi, hem C99 "çift karmaşık" tipi ve C ++ "std :: karmaşık" tipi, operatör aşırı yüklenmesi kullanılarak çoğaltılabilir, eklenebilir, çıkarılabilir, vb.

Ancak C99'da, yerleşik tip olarak başka bir tür ve yerleşik operatör aşırı yükleme desteği eklediler. Ve başka bir yerleşik değişmez özellik eklediler.

C ++ 'da sadece dilin mevcut özelliklerini kullandılar, gerçek özelliğin dilin doğal bir evrimi olduğunu gördüler ve böylece eklediler.

C'de, başka bir tür için aynı gösterim geliştirmeye ihtiyacınız varsa, kuantum dalga işlevlerinizi (veya 3D noktalarınızı veya çalışma alanınızda kullandığınız temel türü) eklemek için lobinize kadar şansınız kalmaz. Yerleşik tip olarak C standardı başarılı.

C ++ 11'de bunu kendiniz yapabilirsiniz:

Point p = 25_x + 13_y + 3_z ; // 3D point

Şişirilmiş mi? Hayır , hem C hem de C ++ komplekslerinin gerçek karmaşık değerlerini temsil etmek için bir yola nasıl ihtiyaç duydukları ile gösterildiği gibi ihtiyaç vardır.

Yanlış mı tasarlanmış? Hayır , genişletilebilirlik göz önünde bulundurularak diğer tüm C ++ özellikleri gibi tasarlanmıştır.

Sadece gösterim amaçlı mıdır? Hayır , kodunuza tip güvenliği bile ekleyebilir.

Örneğin, bir CSS yönelimli kod düşünelim:

css::Font::Size p0 = 12_pt ;       // Ok
css::Font::Size p1 = 50_percent ;  // Ok
css::Font::Size p2 = 15_px ;       // Ok
css::Font::Size p3 = 10_em ;       // Ok
css::Font::Size p4 = 15 ;         // ERROR : Won't compile !

Bu durumda, değerlerin atanmasına güçlü bir yazım uygulamak çok kolaydır.

Tehlikeli mi?

İyi soru. Bu işlevler ad boşluklu olabilir mi? Evetse, Jackpot!

Her neyse, her şey gibi, bir araç yanlış kullanılırsa kendinizi öldürebilirsiniz . C güçlüdür ve C tabancasını kötüye kullanırsanız başınızı vurabilirsiniz. C ++ 'da C tabancası vardır, ancak aynı zamanda neşter, taser ve araç setinde bulabileceğiniz diğer araçlar da vardır. Neşteri kötüye kullanabilir ve kendinizi ölüme kanabilirsiniz. Veya çok zarif ve sağlam bir kod oluşturabilirsiniz.

Yani, her C ++ özelliği gibi, gerçekten ihtiyacınız var mı? C ++ 'da kullanmadan önce cevaplamanız gereken soru budur. Eğer yapmazsan, sana hiçbir maliyeti olmayacak. Ama gerçekten buna ihtiyacınız varsa, en azından dil sizi yarı yolda bırakmaz.

Tarih örneği?

Hatanız, bana öyle geliyor ki, operatörleri karıştırıyorsunuz:

1974/01/06AD
    ^  ^  ^

Bundan kaçınılamaz, çünkü operatör / derleyici onu yorumlamalıdır. Ve AFAIK, bu iyi bir şey.

Sorununuza bir çözüm bulmak için, hazır kelimeyi başka bir şekilde yazardım. Örneğin:

"1974-01-06"_AD ;   // ISO-like notation
"06/01/1974"_AD ;   // french-date-like notation
"jan 06 1974"_AD ;  // US-date-like notation
19740106_AD ;       // integer-date-like notation

Şahsen, tamsayıyı ve ISO tarihlerini seçerdim, ancak bu SİZİN ihtiyaçlarınıza bağlıdır. Bu, kullanıcının kendi gerçek adlarını tanımlamasına izin vermenin tüm noktasıdır.


1
Teşekkürler, ben ve diğer alternatif kişiliklerim keşfedildi. Daha da ciddisi, bunu tek başıma yazdım, ama belki de anadilimin bazı ifadelerini kullanıyorum ve İngilizceye iyi tercüme etmiyorlar.
paercebal

"Farklı bölümlere" gelince, başlıklarına göre, üzgünüm, sanırım bu oldukça uzun bir yazı düzenliyor. Kalın metin gelince, içinde bulundukları paragrafın özeti budur. Sadece gerekçesiz olarak bilgi isteyen insanlar başlıklarda ve kalın metinlerde okumalarını sınırlayabilirler.
paercebal

3
+1. Gerçekten güzel bir açıklama. Bunun uygulanmasını bekliyoruz. Bizim için gerçekten önemli. MDE (Model Odaklı Mühendislik) üzerinde çalışıyoruz ve bunu bir zorunluluk olarak buluyoruz. Aşağıda durumumuzu açıklamak için bir yanıt ekliyorum.
Diego Sevilla

9
@TGV:: Örneğinizi you can write 1+2i, but you still can't write a+bi, so there's absolutely no pointgörmezden gelmek bile a+bisaçma, onu "düşük frekans" olarak algılamanız herkesin yaptığı anlamına gelmez. . . Büyük resme bakıldığında amaç, kullanıcı tanımlı nesnelerin, yerleşik türler gibi dilin birinci sınıf vatandaşları olarak düşünülebildiğinden emin olmaktır. Yazabilir Yani, 1.5fve 1000UL, neden yazamadım 25ibile ya 100101b? C ve Java'nın aksine, kullanıcı türleri C ++ 'da dilin ikinci sınıf vatandaşı olarak kabul edilmemelidir.
paercebal

3
@Anton:: Kodda Most of data still comes from IOçok sayıda sabit kodlanmış değer var. Tüm boolelerde bak, bütün tamsayılar, yazmak için daha uygun olduğu için, kod gelen tüm çiftler x = 2 * y ;yerine x = Two * ynerede Twobir olduğunu kesinlikle yazılan sabiti. Kullanıcı tanımlı değişmez değerler, üzerine bir tür koymamıza ve yazmamıza olanak tanır: x = 2_speed * y ;ve derleyiciden hesaplamanın mantıklı olduğunu doğrulamasını sağlayın. . . Her şey güçlü yazmayla ilgili. . . Belki de kullanmayacaksın. Ama eminim, en kısa zamanda iş yerinde bir C ++ 11 etkin derleyici kullanabilecektir.
paercebal

36

Matematiksel kod için çok güzel. Aklımdan, aşağıdaki operatörlerin kullanımını görebiliyorum:

derece için derece. Bu, mutlak açıları yazmayı çok daha sezgisel hale getirir.

double operator ""_deg(long double d)
{ 
    // returns radians
    return d*M_PI/180; 
}

Ayrıca çeşitli sabit nokta gösterimleri için de kullanılabilir (bunlar DSP ve grafik alanında halen kullanılmaktadır).

int operator ""_fix(long double d)
{ 
    // returns d as a 1.15.16 fixed point number
    return (int)(d*65536.0f); 
}

Bunlar nasıl kullanılacağı konusunda güzel örneklere benziyor. Koddaki sabitlerin daha okunabilir olmasına yardımcı olurlar. Kodu okunamaz hale getirmek için başka bir araçtır, ancak zaten çok fazla araç kötüye kullanımı var ve bir tane daha fazla incitmiyor.


1
"ama biz zaten çok fazla araç kötüye bir daha fazla zarar vermez. " Vay be, umarım bu c ++ [x] 1234567890 özelliği son zamanlarda sel özelliği arkasında felsefe değildir. Bunların tümünü kullanan bir kütüphane, konfigürasyon için on dosya formatı ve kodunuzun ön ve son işlemleri için iki araç öğrenmek zorunda olduğunuzu düşünün ...
masterxilo

@masterxilo Tabii ki, gerçekte, örneğiniz saçma: UDL'leri öğrenmek için işlevlerden daha zor değil, çünkü onlar için sözdizimi şekeri - ve ayrıca, herhangi bir iyi lib sadece UX'i geliştirmek için gereken özellikleri kullanır - ve tam olarak ne olduğunu belgeler tüm araçlar. Birisi okunamayan kod üretmek için bir özelliği gereğinden fazla kullanırsa (çalışma alanında kaçınılmaz olduğunu varsayarsak ...), bu özelliği hataya sokmaz, sadece kullanımı. Ayrıca, bir kişinin okunamayanı diğerinin ekmek ve tereyağıdır. Tüm görüşler - ve seçenekler . Onlardan hoşlanmıyorsanız, endişelenmeyin! Sen yok olması bunları kullanmak için. Diğerleri yapabilir .
underscore_d

17

UDL'ler ad aralıklıdır (ve bildirimler / yönergeler kullanılarak içe aktarılabilir, ancak açıkça bir değişmez alanı adlandıramazsınız 3.14std::i), yani (umarım) bir ton çatışma olmaz.

Aslında ayarlanabilmeleri (ve örtüşmeleri), UDL'lerle oldukça güçlü şeyler yapabileceğiniz anlamına gelir. Bigint yazarları gerçekten mutlu olacaklar, çünkü sonunda derleme zamanında hesaplanan keyfi olarak büyük sabitlere sahip olabilirler (constexpr veya şablonlar aracılığıyla).

Hayali birim siçin std::stringve standart için birkaç faydalı değişmez görmeyeceğimiz için üzgünüm i.

UDL'ler tarafından kaydedilecek kodlama süresinin miktarı aslında o kadar yüksek değildir, ancak okunabilirlik büyük ölçüde artacaktır ve daha fazla hesaplama, daha hızlı yürütme için derleme süresine kaydırılabilir.


İsim alanları hakkındaki noktayı temizlediğiniz için teşekkürler ... Bunu merak ediyordum.
Nathan Reed

12

Biraz bağlam ekleyeyim. Çalışmamız için kullanıcı tanımlı değişmezlere çok ihtiyaç vardır. MDE (Model Odaklı Mühendislik) üzerinde çalışıyoruz. C ++ 'da modeller ve metamodeller tanımlamak istiyoruz. Aslında Ecore'dan C ++ 'a bir eşleme uyguladık ( EMF4CPP ) .

Sorun, model öğelerini C ++ 'da sınıf olarak tanımlayabildiğinizde ortaya çıkar. Metamodeli (Ecore) argümanlı şablonlara dönüştürme yaklaşımını kullanıyoruz. Şablonun argümanları tür ve sınıfların yapısal özellikleridir. Örneğin, iki int niteliğine sahip bir sınıf şöyle bir şey olacaktır:

typedef ::ecore::Class< Attribute<int>, Attribute<int> > MyClass;

Hoever, bir model veya metamodeldeki her elementin genellikle bir adı olduğu ortaya çıkıyor. Yazmak istiyoruz:

typedef ::ecore::Class< "MyClass", Attribute< "x", int>, Attribute<"y", int> > MyClass;

AMA, C ++ veya C ++ 0x buna izin vermez, çünkü dizeler şablonlara argüman olarak yasaklanmıştır. Char adını char ile yazabilirsiniz, ancak bu kesinlikle bir karışıklıktır. Uygun kullanıcı tanımlı değişmez değerlerle benzer bir şey yazabiliriz. Model öğesi adlarını tanımlamak için "_n" kullandığımızı varsayalım (Tam sözdizimini kullanmıyorum, sadece bir fikir oluşturmak için):

typedef ::ecore::Class< MyClass_n, Attribute< x_n, int>, Attribute<y_n, int> > MyClass;

Son olarak, bu tanımların şablon olarak bulunması, gerçekten etkili olan model elemanlarını, model dönüşümlerini, vb.


4
Sevdiğim çok çok fazlaby the compiler at compile time bir bölümünü ... :-)
paercebal

12

Bjarne Stroustrup, bu C ++ 11 konuşmasında , tip açısından zengin arayüzlerin ilk bölümünde yaklaşık 20 dakikalık bir işaretle UDL'lerden bahsediyor .

UDL'ler için temel argümanı bir syllogism biçimini alır:

  1. "Önemsiz" türler, yani yerleşik ilkel türler, yalnızca önemsiz tür hatalarını yakalayabilir. Daha zengin tiplere sahip arayüzler, tip sisteminin daha fazla hata yakalamasını sağlar.

  2. Zengin yazılan kodun yakalayabileceği tür hatalarının gerçek kod üzerinde etkisi vardır. (Önemli bir sabitteki boyut hatası nedeniyle rezil olarak başarısız olan Mars İklim Orbiter örneğini verir).

  3. Gerçek kodda, birimler nadiren kullanılır. İnsanlar bunları kullanmazlar, çünkü zengin türler oluşturmak için çalışma zamanı hesaplaması veya bellek yükü çok pahalıdır ve önceden var olan C ++ şablonlu birim kodunu kullanmak hiç kimse tarafından kullanılmayacak kadar çirkindir. (Ampirik olarak, kütüphaneler on yıldan beri var olmasına rağmen kimse kullanmıyor).

  4. Bu nedenle, mühendislerin birimleri gerçek kodda kullanmasını sağlamak için, (1) çalışma zamanı yükü oluşturmayan ve (2) gösterimsel olarak kabul edilebilir bir cihaza ihtiyacımız vardı.


9

Derleme zamanı boyut kontrolünün desteklenmesi, gereken tek nedendir.

auto force = 2_N; 
auto dx = 2_m; 
auto energy = force * dx; 

assert(energy == 4_J); 

Derleme zamanı boyutlu analiz ve birim / miktar değiştirme ve dönüştürme için küçük bir C ++ 11, C ++ 14 yalnızca başlık kitaplığı olan PhysUnits-CT-Cpp11'e bakın . Daha basit Boost.Units destek yapar ünitesi simgesi örneğin m, G, S olarak hazır bilgi metrik ön yalnızca standart C ++ kütüphanesi boyutlarının, SI-yalnızca tamamlayıcı güçler bağlıdır, örneğin m, k, M olarak.


Veya Nic Holthaus'un bağımlılığı olmayan c ++ 14 üzerine kurulu birimlere , derleme zamanı, yalnızca başlık, boyutsal analiz ve birim dönüştürme kitaplığına bakın .
Martin Moene

6

Hmm ... Bu özelliği henüz düşünmedim. Numuneniz iyi düşünülmüş ve kesinlikle ilginç. C ++ şu anda olduğu gibi çok güçlü, ancak maalesef okuduğunuz kod parçalarında kullanılan sözdizimi bazen aşırı karmaşık. Okunabilirlik, hepsi olmasa da, en azından çok fazladır. Ve böyle bir özellik daha fazla okunabilirlik için tasarlanacaktır. Son örneğini alırsam

assert(1_kg == 2.2_lb); // give or take 0.00462262 pounds

... bugün bunu nasıl ifade edeceğini merak ediyorum. Bir KG ve LB sınıfınız olur ve örtük nesneleri karşılaştırırsınız:

assert(KG(1.0f) == LB(2.2f));

Ve bu da olur. Daha uzun adlara sahip türlerde veya bir adaptör yazmak için böyle güzel bir kurucuya sahip olmayı ummadığınız türlerde, anında örtük nesne oluşturma ve başlatma için iyi bir ek olabilir. Öte yandan, yöntemleri kullanarak nesneleri zaten oluşturabilir ve başlatabilirsiniz.

Ama Nils ile matematik konusunda hemfikirim. Örneğin C ve C ++ trigonometri işlevleri radyan cinsinden girdi gerektirir. Sanırım derece olarak düşünüyorum, bu yüzden Nils gibi çok kısa bir örtülü dönüşüm çok güzel.

Sonuçta, sözdizimsel şeker olacak, ancak okunabilirlik üzerinde hafif bir etkisi olacaktır. Ve muhtemelen bazı ifadeler yazmak daha kolay olacaktır (günah (180.0deg) yazmak günahtan (derece (180.0)) daha kolay olacaktır ve sonra kavramı kötüye kullanan insanlar olacaktır.Ama o zaman dil küfür eden insanlar kullanmalıdır C ++ kadar etkileyici bir şey yerine çok kısıtlayıcı diller.

Ah, görevim temelde hiçbir şey söylemiyor: iyi olacak, etki çok büyük olmayacak. Endişelenmeyelim. :-)


5
Parantezleriniz dengesiz! Üzgünüm, OKB'm de benden nefret ediyor.
X-Istence

3

Bu özelliğe hiç ihtiyaç duymadım veya istemedim (ama bu Blub etkisi olabilir). Diz sarsıntı tepkim, topal olduğu ve muhtemelen ek olarak yorumlanabilecek herhangi bir işlem için operatörün + aşırı yüklenmesinin havalı olduğunu düşünen aynı kişilere hitap etmesidir.


Onaylıyorum: Çok ilginç bir yazı.
paercebal

2

C ++ genellikle kullanılan sözdizimi konusunda çok katıdır - önişlemciyi engellemek, özel bir sözdizimi / dilbilgisi tanımlamak için kullanabileceğiniz çok şey yoktur. Örneğin, mevcut operatörleri aşırı yükleyebiliriz, ancak yenilerini tanımlayamayız - IMO, bu C ++ ruhuyla çok uyumludur.

Daha özelleştirilmiş kaynak kodu için bazı yollar umursamıyorum - ancak seçilen nokta bana çok izole görünüyor, bu da beni en çok karıştırıyor.

Kullanım amacı bile kaynak kodunu okumayı zorlaştırabilir: tek bir harf, bağlamdan hiçbir şekilde tanımlanamayan geniş kapsamlı yan etkilere sahip olabilir. U, l ve f'ye simetri ile, çoğu geliştirici tek harf seçecektir.

Bu, kapsam belirlemeyi de bir soruna dönüştürebilir, küresel ad alanında tek harflerin kullanılması muhtemelen kötü uygulama olarak kabul edilir ve kütüphaneleri daha kolay karıştırmak için kullanılan araçlar (ad alanları ve açıklayıcı tanımlayıcılar) muhtemelen amacını yener.

Destekleme birimleri gibi bir birim kitaplığıyla birlikte "auto" ile birlikte bir miktar değer görüyorum , ancak bu adımı hak etmek için yeterli değil.

Bununla birlikte, ne kadar zekice fikirler ürettiğimizi merak ediyorum.


1
using single letters in global namespace will probably be considered bad practiceAncak bunun bir önemi yoktur: (A) UDL'ler (global olmayan) ad alanı kapsamında tanımlanmalıdır ... muhtemelen (B) yalnızca harf değil,> = 1 harf olmak üzere bir alt çizgiden sonra = = 1 harf içermelidir. küresel NS uygulama için ayrılmıştır. Bu, UDL'lerin doğal olarak kafa karışıklığı yarattığı fikrine karşı en az 2 puan. Özelliğin faydasını azaltarak ad alanını kapsamak zorunda kalmaya gelince, bu nedenle örneğin stdlib inline namespace, kullanıcıların istenirse toptan satış yapabileceğini s olarak bildirir .
underscore_d

2

Bunun gibi ikili dizeler için kullanıcı değişmezleri kullandım:

 "asd\0\0\0\1"_b

std::string(str, n)Oluşturucu kullanarak \0dizeyi yarıya indirmez. (Proje çeşitli dosya formatlarıyla çok çalışmaktadır.)

Bu da std::stringbir sarmalayıcı lehine hendek zaman da yardımcı oldu std::vector.


-5

O şeyde hat gürültüsü çok büyük. Ayrıca okumak korkunç.

Bana haber verin, herhangi bir örnekle yeni sözdizimi eklemesinin mantıklı olduğunu düşündüler mi? Örneğin, zaten C ++ 0x kullanan birkaç program var mı?

Benim için bu kısım:

auto val = 3.14_i

Bu kısmı haklı çıkarmaz:

std::complex<double> operator ""_i(long double d) // cooked form
{ 
    return std::complex(0, d);
}

İ-sözdizimini diğer 1000 satırda da kullansanız bile. Eğer yazarsanız, muhtemelen bunun yanında 10000 satır daha yazıyorsunuzdur. Özellikle de çoğunlukla her yere yazacağınız zaman:

std::complex<double> val = 3.14i

'auto' anahtar kelimesi, yalnızca belki de haklı görülebilir. Ama sadece C ++ alalım, çünkü bu açıdan C ++ 0x'den daha iyidir.

std::complex<double> val = std::complex(0, 3.14);

Sanki .. bu kadar basit. Her yerde kullanırsanız, tüm std ve sivri parantezlerin sadece topal olduğunu düşündüm. Ben hangi sözdizimi st ++ :: karmaşık altında çevirmek için C ++ 0x içinde tahmin etmeye başlamıyorum.

complex = std::complex<double>;

Bu belki de basit bir şey, ama C ++ 0x'de bu kadar basit olduğuna inanmıyorum.

typedef std::complex<double> complex;

complex val = std::complex(0, 3.14);

Belki? > :)

Her neyse, nokta: std :: complex (0, 3.14) yerine 3.14i yazmak; birkaç süper özel durum haricinde genel olarak fazla zaman kazandırmaz.


10
@Cheery: Sizin için "auto val = 3.14i" bunu desteklemek için yazılan kodu haklı çıkarmaz. Benim için "printf ("% i ", 25)" printf için yazılan kodu haklı çıkarmaz. Bir desen görüyor musunuz?
paercebal

5
@Cheery: "O şeyde hat gürültüsü çok büyük". Hayýr, deđil ... "Ayrıca okumak korkunç". Sübjektif argümanınız ilginç, ancak bu özelliğin kodunun şaşırtıcı / şok edici olmaktan çok uzak olduğunu görmek için genel olarak aşırı yükleme operatörüne bir göz atmalısınız ... C ++ geliştiricisi için
paercebal

3
otomatik okunabilirliğe yardımcı olur. for döngüsünde interator kullanmayı düşünün: for (auto it = vec.begin (); it! = vec.end (); ++ it) ... for_each hakkında biliyorum, ancak kullanmak için bir functor oluşturmak zorunda değilsiniz .
KitsuneYMG

1
@kts: C ++ 1x ile lambda ve menzilimiz olacak
Joe D

3
C ++ satırınız C ++ 0x'den daha iyiyse, satırım henüz daha iyidir. Sadece yazın: std::complex<double> val(0, 3.14);.
Ben Voigt
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.