C ++ neden anonim yapılara izin vermiyor?


93

Bazı C ++ derleyicileri, anonim birleşimlere ve yapılara standart C ++ 'nın bir uzantısı olarak izin verir. Bazen çok yardımcı olan biraz sözdizimsel şekerdir.

Bunun standardın bir parçası olmasını engelleyen mantık nedir? Teknik bir engel var mı? Felsefi mi? Yoksa haklı göstermeye yetecek kadar mı yok?

İşte bahsettiğim şeyin bir örneği:

struct vector3 {
  union {
    struct {
      float x;
      float y;
      float z;
    };
    float v[3];
  };
};

Derleyicim bunu kabul edecek, ancak "isimsiz yapı / birleşim" in standart olmayan bir C ++ uzantısı olduğu konusunda uyarıyor .


3
Açıkçası, ne demek istediğin konusunda bazı karışıklıklar var. Yalnızca bir derleyici uzantısı nedeniyle derlenen bir kod örneği verebilir misiniz?
Rob Kennedy

75
Kulağa benzer gelen ancak büyük ölçüde farklı olan iki kavram olduğuna dikkat edin: adsız yapılar ve anonim yapılar . İlki, C ++ tarafından desteklenen şudur: struct { int i; } a; a.i = 0;(türün adı yoktur). İkinci C ++ etmez bu, olduğu değildir : destek struct { int i; }; i = 0;(tip bir ismi yoktur ve çevre kapsamına kaçar). C ++, ancak, yapar hem isimsiz ve anonim destekleyen sendikalar .
Johannes Schaub -

Bu oldukça ilginç VMMLib vektör kitaplığına benziyor. Sorunun sendikanın isimsiz bir yapı içermesi olduğuna inanıyorum, ama emin değilim.
greyfade

1
FWIW Bu yönettiği "anonmyous", "isimsiz" değil ve sendikalar vardır LITB söylediği gibi destekledi. stackoverflow.com/q/14248044/560648
Yörüngede Hafiflik Yarışları

1
@AdrianMcCarthy: Bu iyi (FSVO "iyi"; sinir bozucu derleyici şifreli), ama kesinlikle "isimsiz", alakasız, standart bir kavram.
Orbit'te Hafiflik Yarışları

Yanıtlar:


50

Başkalarının da belirttiği gibi, anonim birliklere standart C ++ ile izin verilir, ancak anonim yapılara izin verilmez.

Bunun nedeni, C'nin anonim birleşimleri desteklemesi, ancak anonim yapıları * desteklememesidir, bu nedenle C ++ uyumluluk için ilkini destekler, ancak uyumluluk için gerekli olmadığı için ikincisini desteklemez.

Ayrıca, C ++ 'da anonim yapıların pek bir faydası yoktur. Gösterdiğiniz kullanım, üç kayan nokta içeren bir yapıya sahip olmak için ya .v[i], ya da .x, ile başvurulabilir .yve .zC ++ 'da tanımsız davranışla sonuçlandığına inanıyorum. C ++, bir sendikanın bir üyesine yazmanıza, örneğin .v[1]başka bir üyeden okumanıza izin vermez .y. Bunu yapan kod alışılmadık bir durum olmasa da aslında iyi tanımlanmamıştır.

C ++ 'ın kullanıcı tanımlı türler için olanakları alternatif çözümler sağlar. Örneğin:

struct vector3 {
  float v[3];
  float &operator[] (int i) { return v[i]; }
  float &x() { return v[0]; }
  float &y() { return v[1]; }
  float &z() { return v[2]; }
};

* C11, görünüşe göre anonim yapılar ekler, bu nedenle C ++ 'nın gelecekteki bir revizyonu bunları ekleyebilir.


2
+1: Örneğim C ++ 'daki tanımlanmamış davranışa dayanıyor - soruyu yazdığım zaman farkında olmadığım bir şey.
Adrian McCarthy

2
"C ++, bir sendikanın bir üyesine yazmanıza [...] ve sonra başka bir üyeden okumanıza izin vermez" - söz konusu üyeler standart düzen nesneleri olmadıkça ve kendi üyelerinden ortak bir başlangıç ​​sırasını paylaşmadıkça ve siz ' yeniden yazma / okuma bunların söz konusu ortak başlangıç dizisi içindeki üyeleri. Bu, bir evcil (yani tanımlanmıştır).
underscore_d

5
@underscore_d: Evet, türler ortak bir başlangıç ​​dizisine sahip standart düzendeyse. Bununla birlikte, bir yapı hiçbir zaman bir diziye bu şekilde takma ad veremez , çünkü C ++ "ortak ilk sıra" kuralları, ortak bir başlangıç ​​dizisinin yalnızca yapılar arasında olabileceğini belirtir . Dizilerden bahsedilmez, bu nedenle bu şekilde takma ad olamazlar.
Nicol Bolas

@NicolBolas Oh, haha ​​- inan bana - defalarca dizilerin ve diğer ilkellerin bu ödeneğe dahil edilmesini diledim! Ancak bununla ilgili olası pratik sınırlamalar hakkında fazla düşünmedim, bu yüzden muhtemelen şu anda göründüğü kadar basit değil. Yorumum daha genel ama kudreti ettik o eklenmesi için çok teşekkürler, ben bu dahil edildi diziler düşündüm ihmal ima tehlikeye attı.
underscore_d

"Bunun nedeni, C'nin anonim sendikaları desteklemesi, ancak anonim yapıları desteklememesidir." - Hayır. Dipnotunuz, burada C99 veya daha önceki sürümlerden bahsettiğinizi açıklıyor. "Anonim birleşim" terimi C99 standardının hiçbir yerinde görünmez. GCC, bir tanılamada (-std = c99 -pedantic seçenekleriyle) "ISO C99'un adsız yapıları / birlikleri desteklemediğini" iddia ediyor. Standart, isimsiz bit alanları dışında isimsiz üyeler hakkında hiçbir şeyden bahsetmez. Yapısal bildirimler bildirim olup olmadığından tam olarak emin değilim, ancak öyleyse, anonim sendikalar en iyi ihtimalle tanımlanmamış 6.7p2'ye göre bir kısıtlama ihlalidir.

21

Diyorum ki, vector3beyanınızı sadece bir kullanarak temizleyebilirsinizunion

union vector3 {
  struct { float x, y, z; } ;
  float v[3] ;
} ;

Tabii, anonim yapılar oldu bir MSVC uzantısı . Ancak ISO C11 artık buna izin veriyor ve gcc ve Apple'ın llvm derleyicisi de buna izin veriyor .

Neden C11'de değil de C ++ 11'de? Emin değilim, ancak pratik olarak konuşursak çoğu (gcc ++, MSVC ++ ve Apple'ın C ++ derleyicisi) C ++ derleyicileri bunları destekler.


1
Güncellenen bilgiler için +1. Dış yapıya sahip olmamın nedeni, "gerçek kodun" da yöntemleri olmasıydı.
Adrian McCarthy


2
Teşekkürler. Asla yeni bir sendika, bir yapı veya sınıf gibi kullanılamaz.
Adrian McCarthy

Sun Studio'nun varsayılan olarak C ++ 11'den önce anonim yapıyı desteklemediğini biliyorum. Çapraz platform kodu yazıyorsanız ve derleyiciler C + 11'e yükseltilmediyse anonim yapı kullanmayın.
irsis

5

Ne demek istediğinden emin değilim. C ++ şartnamesinin 9.5.Bölümü, madde 2:

Form birliği

union { member-specification } ;

anonim sendika denir; isimsiz tipte isimsiz bir nesneyi tanımlar.

Bunun gibi şeyler de yapabilirsiniz:

void foo()
{
  typedef
  struct { // unnamed, is that what you mean by anonymous?
    int a;
    char b;
  } MyStructType; // this is more of a "C" style, but valid C++ nonetheless

  struct { // an anonymous struct, not even typedef'd
    double x;
    double y;
  } point = { 1.0, 3.4 };
}

Her zaman çok yararlı değil ... bazen kötü makro tanımlarında yararlı olsa da.


12
-1 çünkü anonim bir yapıyı tanımladığını söylüyor. Soruyla ilgili yukarıdaki yorumlara bakın - anonim değil, adsız bir yapı tanımlıyorsunuz.
Johannes Schaub - litb

1

Sendikalar isimsiz olabilir; Standart 9.5 paragraf 2'ye bakınız.

Anonim bir yapı veya sınıfın hangi amacı yerine getirdiğini düşünüyorsunuz? Bir şeyin neden Standartta olmadığını tahmin etmeden önce, neden olması gerektiği konusunda biraz fikir sahibi olmak istiyorum ve anonim bir yapı için bir kullanım görmüyorum.


1

Düzenlemeye, yorumlara ve şu MSDN makalesine dayanarak: Anonim Yapılar , bir tahminde bulunacağım - kapsülleme kavramına pek uygun değil. Bir sınıf üyesinin, yalnızca bir üye eklemenin ötesinde sınıf ad alanımla uğraşmasını beklemem. Ayrıca, anonim yapıdaki değişiklikler sınıfımı izinsiz etkileyebilir.


1
Anonim yapıların / birleşmelerin yaratılma şekli nedeniyle (bir makro haricinde gizlenemeyen özel, satır içi sözdizimi), kullandığınız bazı üyelerin anonim bir üye olmasına şaşıramazsınız. Dolayısıyla bu mantığın mantıklı olduğunu düşünmüyorum. Asıl neden, anonim birleşimlerin yalnızca C uyumluluğu için C ++ ' da desteklenmesidir. C anonim yapıları (C11'e kadar) desteklemez ve dolayısıyla C ++ da desteklemez.
bames53

1

Senin kodun

union {
  struct {
    float x;
    float y;
    float z;
  };
  float v[3];
};

gibi

union Foo {
   int;
   float v[3];
};

bu kesinlikle geçersizdir (C99'da ve öncesinde).

Nedeni muhtemelen ayrıştırmayı (C'de) basitleştirmektir, çünkü bu durumda yalnızca struct / union gövdesinin yalnızca "bildirici ifadeleri" olup olmadığını kontrol etmeniz gerekir.

Type field;

Bununla birlikte, gcc ve "diğer derleyiciler" adsız alanları uzantı olarak destekler.

Düzenleme: Anonim yapılar artık resmi olarak C11'de desteklenmektedir (§6.7.2.1 / 13).


5
Ayrıştırma açısından, bunun bundan union { ... }farklı olduğunu düşünmüyorum struct { ... }. İlki geçerlidir, ancak ikincisi değildir.
Johannes Schaub -

3
Genel olarak C ++ 'nın ayrıştırılmasının ne kadar saçma bir şekilde zor olduğu düşünüldüğünde, ayrıştırmayı basitleştirmek için standart adanmış izin verilmeyen adsız yapıların ve birleşimlerin olduğundan şüpheliyim.
Adrian McCarthy

@Adrian: C dedim, C ++ değil. C ++, C'nin sözdizimini benimser ve genişletir. Muhtemelen C ++ 'ın yaratıcıları isimsiz yapı / birleşim üyelerine izin verme gereğini görmezler, böylece sözdiziminin bu kısmıyla uğraşmazlar.
kennytm

@Adrian, İyi nokta Adrian, "Uygulamanın çok zor olduğunu" her zaman Bjarne ve ekibinin endişesi olacağını
düşünmemiştim

C ve C ++ her ikisi de adsız birleşimleri destekler, bu nedenle union { ... };geçersiz olan yorum doğru değildir.
bames53
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.