Cevabın iki bölümü var. Derleyici düzeyinde uyumluluk ve bağlayıcı düzeyinde uyumluluk. Eski ile başlayalım.
tüm başlıkların C ++ 11'de yazıldığını varsayalım
Aynı derleyiciyi kullanmak, aynı standart kitaplık üstbilgisinin ve kaynak dosyalarının (derleyiciyle ilişkilendirilmiş onces) hedef C ++ standardına bakılmaksızın kullanılacağı anlamına gelir. Bu nedenle, standart kitaplığın başlık dosyaları, derleyici tarafından desteklenen tüm C ++ sürümleriyle uyumlu olacak şekilde yazılır.
Bununla birlikte, bir çeviri birimini derlemek için kullanılan derleyici seçenekleri belirli bir C ++ standardını belirtiyorsa, yalnızca yeni standartlarda mevcut olan herhangi bir özelliğe erişilememelidir. Bu, __cplusplus
direktif kullanılarak yapılır . Nasıl kullanıldığına dair ilginç bir örnek için vektör kaynak dosyasına bakın . Benzer şekilde, derleyici standardın daha yeni sürümleri tarafından sunulan sözdizimsel özellikleri reddedecektir.
Tüm bunlar, varsayımınızın yalnızca yazdığınız başlık dosyalarına uygulanabileceği anlamına gelir. Bu başlık dosyaları, farklı C ++ standartlarını hedefleyen farklı çeviri birimlerine dahil edildiğinde uyumsuzluklara neden olabilir. Bu, C ++ standardının Ek C'de tartışılmaktadır. 4 cümle var, sadece ilkini tartışacağım ve geri kalanından kısaca bahsedeceğim.
C.3.1 Madde 2: sözcük kuralları
Tek tırnak işaretleri, C ++ 11'de bir karakter hazır bilgisini sınırlarken, bunlar C ++ 14 ve C ++ 17'de rakam ayırıcılardır. Saf C ++ 11 başlık dosyalarından birinde aşağıdaki makro tanımına sahip olduğunuzu varsayalım:
#define M(x, ...) __VA_ARGS__
int x[2] = { M(1'2,3'4) };
Başlık dosyasını içeren, ancak sırasıyla C ++ 11 ve C ++ 14'ü hedefleyen iki çeviri birimini düşünün. C ++ 11 hedeflenirken, tırnak işaretleri içindeki virgül bir parametre ayırıcı olarak kabul edilmez; sadece bir kez parametre vardır. Bu nedenle, kod şuna eşdeğer olacaktır:
int x[2] = { 0 };
Öte yandan, C ++ 14 hedeflenirken, tek tırnaklar basamak ayırıcılar olarak yorumlanır. Bu nedenle, kod şuna eşdeğer olacaktır:
int x[2] = { 34, 0 };
Buradaki nokta, saf C ++ 11 başlık dosyalarından birinde tek tırnak kullanmanın, C ++ 14 / 17'yi hedefleyen çeviri birimlerinde şaşırtıcı hatalara neden olabileceğidir. Bu nedenle, bir başlık dosyası C ++ 11'de yazılsa bile, standardın sonraki sürümleriyle uyumlu olduğundan emin olmak için dikkatli bir şekilde yazılmalıdır. __cplusplus
Direktif burada yararlı olabilir.
Standarttaki diğer üç madde şunları içerir:
C.3.2 Madde 3: temel kavramlar
Değişiklik : Yeni olağan (yerleştirme dışı) ayırıcı
Gerekçe : Boyut ayırma için gereklidir.
Orijinal özellik üzerindeki etki : Geçerli C ++ 2011 kodu, aşağıdaki gibi bir genel yerleşim ayırma işlevi ve serbest bırakma işlevi bildirebilir:
void operator new(std::size_t, std::size_t);
void operator delete(void*, std::size_t) noexcept;
Bununla birlikte, bu Uluslararası Standartta, operatör silme beyanı, önceden tanımlanmış bir olağan (yerleştirme olmayan) operatör silme (3.7.4) ile eşleşebilir. Eğer öyleyse, program, sınıf üyesi tahsis fonksiyonları ve serbest bırakma fonksiyonları (5.3.4) için olduğu gibi biçimsizdir.
C.3.3 Madde 7: beyanlar
Değiştir : constexpr statik olmayan üye işlevleri örtük olarak const üye işlevleri değildir.
Gerekçe : constexpr üye işlevlerinin nesneyi değiştirmesine izin vermek için gereklidir.
Orijinal özellik üzerindeki etki : Geçerli C ++ 2011 kodu bu Uluslararası Standartta derlenemeyebilir.
Örneğin, aşağıdaki kod C ++ 2011'de geçerlidir ancak bu Uluslararası Standartta geçersizdir çünkü aynı üye işlevini farklı dönüş türleriyle iki kez bildirir:
struct S {
constexpr const int &f();
int &f();
};
C.3.4 Madde 27: girdi / çıktı kitaplığı
Değişiklik : alır tanımlı değil.
Gerekçe : Get kullanımı tehlikeli kabul edilir.
Orijinal özellik üzerindeki etki : gets işlevini kullanan geçerli C ++ 2011 kodu bu Uluslararası Standartta derlenemeyebilir.
C ++ 14 ve C ++ 17 arasındaki olası uyumsuzluklar C.4'te tartışılmaktadır. Standart olmayan tüm üstbilgi dosyaları (soruda belirtildiği gibi) C ++ 11'de yazıldığı için bu sorunlar ortaya çıkmayacağı için burada bunlardan bahsetmeyeceğim.
Şimdi bağlayıcı düzeyinde uyumluluğu tartışacağım. Genel olarak, uyumsuzlukların olası nedenleri arasında şunlar yer alır:
Elde edilen nesne dosyasının formatı hedef C ++ standardına bağlıysa, bağlayıcının farklı nesne dosyalarını bağlayabilmesi gerekir. GCC, LLVM ve VC ++ 'da neyse ki durum böyle değil. Yani, nesnelerin dosyalarının biçimi, derleyicinin kendisine büyük ölçüde bağımlı olmasına rağmen, hedef standarttan bağımsız olarak aynıdır. Aslında, GCC, LLVM ve VC ++ bağlayıcılarından hiçbiri hedef C ++ standardı hakkında bilgi gerektirmez. Bu ayrıca, önceden derlenmiş nesne dosyalarını bağlayabileceğimiz anlamına gelir (çalışma zamanını statik olarak bağlayarak).
Program başlatma yordamı (çağıran işlev main
) farklı C ++ standartları için farklıysa ve farklı yordamlar birbiriyle uyumlu değilse, nesne dosyalarını bağlamak mümkün olmayacaktır. GCC, LLVM ve VC ++ 'da neyse ki durum böyle değil. Ek olarak, main
işlevin imzası (ve onun üzerinde geçerli olan kısıtlamalar, standardın 3.6 Bölümüne bakın) tüm C ++ standartlarında aynıdır, dolayısıyla hangi çeviri biriminde bulunduğu önemli değildir.
Genel olarak, WPO, farklı C ++ standartları kullanılarak derlenen nesne dosyalarıyla iyi çalışmayabilir. Bu, derleyicinin tam olarak hangi aşamalarının hedef standart hakkında bilgi gerektirdiğine ve hangi aşamaların gerektirmediğine ve nesneler arasındaki prosedürler arası optimizasyonlar üzerindeki etkisine bağlıdır. Neyse ki, GCC, LLVM ve VC ++ iyi tasarlanmış ve bu soruna sahip değil (bildiğim kadarıyla değil).
Bu nedenle, GCC, LLVM ve VC ++ , C ++ standardının farklı sürümleri arasında ikili uyumluluğu sağlamak için tasarlanmıştır . Yine de bu, standardın kendisinin bir gereği değildir.
Bu arada, VC ++ derleyicisi , C ++ standardının belirli bir sürümünü hedeflemenizi sağlayan std anahtarını sunsa da , C ++ 11'i hedeflemeyi desteklemez. Belirtilebilecek minimum sürüm, Visual C ++ 2013 Güncellemesi 3'ten başlayarak varsayılan olan C ++ 14'tür. C ++ 11'i hedeflemek için daha eski bir VC ++ sürümü kullanabilirsiniz, ancak daha sonra farklı VC ++ derleyicileri kullanmanız gerekir. en azından WPO'yu bozacak olan C ++ standardının farklı sürümlerini hedefleyen farklı çeviri birimlerini derlemek.
CAVEAT: Cevabım tam veya çok kesin olmayabilir.