2014-10-04 26 views
7

, gcc aşağıdaki işleri ancak clang üzerinde değil ki (see it live) Nasıl yani: Statik constexpr kullandı mı, kullanılmıyor mu?

constexpr int giveMeValue() { return 42; } 

struct TryMe { 
    static constexpr int arr[1] = { 
     giveMeValue() 
    }; 
}; 

int main() { 
    int val = TryMe::arr[0]; 
    return val; 
} 

Ben clang çözülmemiş bir dış sembolü olsun.

TryMe::arr[0] bir nesnedir? Eğer öyleyse, kullanıldı mı?

+1

Hangi versiyonda? –

+0

Biri coliru – Dean

+0

'daki işler benim için uygun: http://coliru.stacked-crooked.com/a/2b319b9351784244 "C++ 11 flag" özelliğini açtınız mı? – texasbruce

cevap

7

TryMe::arrodr-used ama bir tanım (see it live) vermeyin:

constexpr int TryMe::arr[1]; 

Neden gcc ve clang arasındaki tutarsız sonucudur?

Her programı her sigara satır içi tam olarak bir tanımını içermelidir: ODR ihlalleri, bir disagnostic gerektirmeyen C++ 11 ve C++ 14 taslak standardına (vurgu mayın) hem olmasıdır Bu programda kullanılmayan işlevi veya değişkeni; tanılamadı gerekli.

Biz görmek diyor taslak C++ 11 standart bölüm 3.2 den ODR kullanılan: bu bir unevaluated işlenen olmadıkça

bir ifade potansiyel değerlendirilir (Madde 5) veya bunun bir alt ifadesidir. ismi, potansiyel olarak değerlendirilen bir ifade olarak görünen bir değişken sabit (5.19) ifadesinde görünme gereksinimlerini karşılayan bir nesne ve hemen geçerli olan lvalue-to-dönüşüm (4.1) değeri uygulamalı.

TryMe::arr bir amacı olup, sabit bir ifadede görünüp lvalue-için-rvalue dönüşüm hemen TryMe::arr ancak TryMe::arr[0] uygulanmadığı için gereksinimleri karşılamak yapar.

bir hata raporu (DR 712) üzerinden hem de o tatbik beri C++, 11 için de geçerlidir taslak C++ 14 standart güncelleştirilmiş ifadeler: ismi görünür

bir değişken x Olası olarak değerlendirilen ifade olarak ex, lvalue-to-rival dönüşümünü (4.1) 'un x'e uygulanmaması, herhangi bir önemsiz olmayan işlevi çağırmayan sabit bir ifade (5.19) vermediği ve x ise object, ex,adresindeki ifade ifadesinin olası sonuçlarının bir öğesidir.lvalue-için-rvalue dönüşüm (4.1) e tatbik edilir, veya e bir atılır değer ifade

olan 3.2 paragraf 2 ve bu ekspresyon TryMe::arr[0] arasında kriterlerine göre boş potansiyel sonuçlar Bu odr-kullanılır.

Not: her bölüm için, sınıfının dışında bir tanımını sağlamak gerekir 9.4.2[class.static.data] der (vurgu madeni) hazır bilgi

bir statik veri elemanı Constexpr belirteci ile sınıf tanımında bildirilebilir; eğer öyleyse, beyanı , bir atama-ifadesi olan tüm başlatıcı-madde 'un sabit bir ifadesi olduğu bir küme-eşit-başlatıcıyı belirtir. [Not: her iki durumda da, üye sabit ifadelerde görünebilir. -end not] o bir başlatıcı

Güncelleştirme içermemelidir programı ve ad kapsamı tanımlama (3.2) kullanılan ODR-ise, elemanı yine bir isim alanı kapsamına tanımlanacaktır

TC 3.2 aşağıdaki mermi ekler defect report 1926 işaret [basic.def.odr] paragraf 2:

  • E, bir dizi terimin bir Altsimgeleme işlemi (5.2.1 [expr.sub]) ise, set o işlenenini içerir.

hangi bir dizi subscripting artık ODR kullanım ve bu yüzden OP'ler kod C++ 1Z iyi oluşmuş ve bu gibi kusur görünür çünkü C++ 14 gibi görünüyor olacaktır demektir C++'ye karşı 14.

+0

Açıklama ve tanımlamayla ilgili daha fazla açıklama. OP'nin kendi TryMe yapısında sahip olduğu bir tanım olarak görünebilir, ama aslında bir deklarasyonun bir tanım olduğu zamanki komik kurallar nedeniyle bir beyannamedir.Burada OP bir "statik" değişkeni, genellikle izin verilmeyen bir sınıf içi üye başlatıcısı ile vardır, ancak burada "constexpr" (ve "int") nedeniyle izin verilir. Ancak, OP aslında 'TryMe :: arr' için bellek ayırmamıştır, çünkü değişken de harici depolama gerektiren bir statiktir. Yani, herhangi bir "statik" değişkeni gibi, OP hala yapının dışında bir bildirimde bulunmalıdır. – AndyG

+0

(Odadan çıktığım için önceki yoruma devam ediyorum). Ancak, 'tryMe' yapısını tanımlamak isteyen herhangi bir sınıf olduğu için OP'nin' TryMe 'yapısını tanımladığı aynı dosyada 'constexpr int' TryMe :: arr [1]; Daha sonra One Definition Kuralı'nı ihlal eden 'TryMe :: arr [1]' için depolama alanı ayırmaya çalışın. Bunun yerine, genellikle bunun yerine, 'Constexpr int' TryMe :: arr [1] 'i birer birer .cpp dosyasında, başlıktan ayrı olacak şekilde koyarsınız. – AndyG

+0

@AndyG adil bir nokta, biraz bilgi aldım, daha detaylı eklemeliydim. Daha fazla ayrıntı eklememe izin verin. –

İlgili konular