2015-01-22 17 views
10

Aşağıdaki C++ 11 kodunda, arraySize için yapılan son çağrı bir derleme hatasına neden olur. Görünüşe göre bu, y'nin çalışma zamanı boyutundaki bir dizidir ve arraySize şablon parametresi N, y için çıkarılabilir. X'in neden derlenmiş bir zaman boyutlu dizi olduğunu anlamıyorum, ancak y çalışma zamanının büyüklüğünü tamamlıyor. DiziBüyüklüğü şablon işlevi C++ Scott Meyers' 'Etkili Modern C++' Öğe 1.C++: Neden bu constexpr bir derleme zaman sabiti değil

#include <cstddef> 

template<typename T, std::size_t N> 
constexpr std::size_t arraySize(T(&)[N]) noexcept { return N; } 

struct S 
{ 
    char c[10]; 
}; 

int main() 
{ 
    S s; 
    S* ps = &s; 

    char x[arraySize(s.c)]; 
    char y[arraySize(ps->c)]; // why is y a runtime sized array? 

    arraySize(x); 
    arraySize(y); // error !? 

    return 0; 
} 
+0

Hata nedir? –

+0

ben de stumped ... hem 'sc' ve hem de ps-> c' 'türid (sc) .name()' veya 'typeid (ps-> c) .name ile yayılanla aynı türde() ', yaniG ++ – vsoftco

+0

için A10_c'yi ​​biraz daha koyulaştırmak için: eğer 'arraySize()' ın parametresine bir referans-const yapısını yaparsanız, aşağıdaki derlemeler: 'char y [arraySize (decltype (ps-> c) {})]; ' – Quentin

cevap

9

doğrudan alınır, hata arraySize(y) çağrısı, ancak y kendisinin beyanı değildir.

Bir dizi bildirimindeki sınırlar "dönüştürülmüş sabit ifade" olmalıdır.

Derleyiciniz, y bildirimini kabul ederse ve daha sonra, y'un bir çalışma zamanı dizisi olduğunu bildirirse, bu bir C++ derleyicisi değildir. C++ 'nın onaylanmış herhangi bir sürümünde ne zaman çalışma zamanı dizisi ne de mevcut taslak var.

arraySize(s.c) ve arraySize(ps->c) arasında anlamlı bir farklılık (aşağıya bakınız, ne &s olan) ps->c(*ps).c ile aynıdır ve * KQUEUE operatör sabit bir ifade değildir ps üzerinde lvalue-için-rvalue dönüşüm, gerektirmesidir. İfadenin geri kalanı lvalue-to-rival dönüşüm içermez, dizi lvalue doğrudan referans ile bağlanır.

sabit bir ifadesidir ya değeri (aşağıda tanımlandığı gibi), sabit bir ifade izin sonucu bir varlığa işaret eder bir glvalue çekirdek sabit ifade veya değeri burada bir amacı, bir prvalue çekirdek sabit ifade bu nesne ve alt nesnelerin:

  • referans türü olmayan her statik veri elemanı, bir sabit ifade izin sonucu bir varlığa işaret eder, ve

  • ı Nesne veya alt nesne işaretçi türündeyse, statik depolama süresine sahip bir nesnenin adresini, bu nesnenin sonundaki adresi (5.7), bir işlevin adresini veya bir boş gösterici değerini içerir. öyle değil geçici bir nesne olduğunu veya değeri satis fi es yukarıdaki kısıtlamalar geçici nesne mi, yoksa bir statik depolama süresine sahip bir nesne olup olmadığını

Bir işletme sabit bir ifade izin sonucudur işlevi.

Açıkça ps otomatik depolama süresi ile bir nesnenin adresini içerir, bu nedenle constexpr ilan edilemez. Ama her şey statik depolama bir nesneye bir başvuru olup beri, sen arraySize(s.c) parametresini sabit ifadesi ya olmadığını düşünmek istiyorum diğer yandan (S s; S* ps = &s;

static S s; constexpr S* ps = &s; geçtiğinizdeyse çalışmaya başlamalıdır süre)

+0

"Derleyiciniz y bildirimini kabul ederse ve daha sonra, çalışma zamanının bir dizi çalışma zamanı olduğunu söylerse, bu bir C++ derleyici değildir." - Bu bölüm doğru değildir, uygun bir uygulama (derleyici), açıkça biçimlendirilmiş girdinin uzantı yolu ile "kabul edilmesi" (yani, derlenmesi ve/veya yürütülmesi) için açıkça izin verilir, bkz. N4296 taslağında 1.4/8. Bu durumda ** bir diyagnostik oluşturmak için ** uygulaması gereklidir ve GCC ve clang -pedantic seçeneği çağırmaya eklenmedikçe değişken uzunlukta diziler için bir uyarı yayınlayamaz. –

İlgili konular