/Zc:twoPhase-
(iki aşamalı ad aramasını devre dışı bırak)
/Zc:twoPhase-
altında /permissive-
seçeneği, derleyiciye sınıf şablonlarını ve işlev şablonlarını ayrıştırmak ve örneklendirmek için özgün, uyumlu olmayan Microsoft C++ derleyici davranışını kullanmasını söyler.
Sözdizimi
/Zc:twoPhase-
Açıklamalar
Visual Studio 2017 sürüm 15.3 ve üzeri: altında /permissive-
, derleyici şablon adı çözümlemesi için iki aşamalı ad araması kullanır. ayrıca belirtirseniz /Zc:twoPhase-
, derleyici önceki uyumsuz sınıf şablonuna ve işlev şablonu ad çözümlemesine ve değiştirme davranışına geri döner. Belirtilmediğinde /permissive-
, uyumsuz davranış varsayılandır.
Sürüm 10.0.15063.0 (Creators Update veya RS2) ve önceki sürümlerdeki Windows SDK üst bilgi dosyaları uyumluluk modunda çalışmaz. /Zc:twoPhase-
kullandığınızda /permissive-
bu SDK sürümleri için kod derlemek için gereklidir. Windows SDK'nın sürüm 10.0.15254.0 (Fall Creators Update veya RS3) ile başlayan sürümleri uyumluluk modunda düzgün çalışır. Seçeneği gerektirmezler /Zc:twoPhase-
.
Kodunuzun doğru derlenmiş olması için eski davranışı gerektiriyorsa kullanın /Zc:twoPhase-
. Kodunuzu standarda uyacak şekilde güncelleştirmeyi kesinlikle göz önünde bulundurun.
Altında derleyici davranışı /Zc:twoPhase-
Varsayılan olarak veya visual studio 2017 sürüm 15.3 ve sonraki sürümlerinde hem hem /Zc:twoPhase-
de /permissive-
belirttiğinizde derleyici şu davranışı kullanır:
Yalnızca şablon bildirimini, sınıf başlığını ve temel sınıf listesini ayrıştırıyor. Şablon gövdesi bir belirteç akışı olarak yakalanır. Hiçbir işlev gövdesi, başlatıcı, varsayılan bağımsız değişken veya noexcept bağımsız değişkeni ayrıştırılmaz. Sınıf şablonu, sınıf şablonundaki bildirimlerin doğru olduğunu doğrulamak için belirsiz bir türde sahte örnek oluşturulur. Şu sınıf şablonunu göz önünde bulundurun:
template <typename T> class Derived : public Base<T> { ... }
Şablon bildirimi, ,
template <typename T>
sınıf başıclass Derived
ve temel sınıf listesipublic Base<T>
ayrıştırılır, ancak şablon gövdesi belirteç akışı olarak yakalanır.Bir işlev şablonunu ayrıştırdığında, derleyici yalnızca işlev imzasını ayrıştırıyor. İşlev gövdesi hiçbir zaman ayrıştırılır. Bunun yerine belirteç akışı olarak yakalanır.
Sonuç olarak, şablon gövdesinde söz dizimi hataları varsa ancak şablon hiçbir zaman örneği alınmazsa, derleyici hataları tanılamaz.
Bu davranışın bir diğer etkisi de aşırı yükleme çözümlemesidir. Belirteç akışının örnek oluşturma sitesinde genişletilmesi nedeniyle standart olmayan davranışlar oluşur. Şablon bildiriminde görünür olmayan simgeler, örnek oluşturma noktasında görülebilir. Bu, aşırı yükleme çözümlemeye katılabilecekleri anlamına gelir. Şablonların, standartın aksine şablon tanımında görünür olmayan koda göre davranışını değiştirdiğini görebilirsiniz.
Örneğin, aşağıdaki kodu düşünün:
// zctwophase.cpp
// To test options, compile by using
// cl /EHsc /nologo /W4 zctwophase.cpp
// cl /EHsc /nologo /W4 /permissive- zctwophase.cpp
// cl /EHsc /nologo /W4 /permissive- /Zc:twoPhase- zctwophase.cpp
#include <cstdio>
void func(long) { std::puts("Standard two-phase") ;}
template<typename T> void g(T x)
{
func(0);
}
void func(int) { std::puts("Microsoft one-phase"); }
int main()
{
g(6174);
}
Derleyici seçenekleriyle /Zc:twoPhase-
varsayılan modu, uyumluluk modunu ve uyumluluk modunu kullandığınızda aşağıdaki çıktıyı görebilirsiniz:
C:\Temp>cl /EHsc /nologo /W4 zctwophase.cpp && zctwophase
zctwophase.cpp
Microsoft one-phase
C:\Temp>cl /EHsc /nologo /W4 /permissive- zctwophase.cpp && zctwophase
zctwophase.cpp
Standard two-phase
C:\Temp>cl /EHsc /nologo /W4 /permissive- /Zc:twoPhase- zctwophase.cpp && zctwophase
zctwophase.cpp
Microsoft one-phase
altında uyumluluk modunda /permissive-
derlendiğinde, derleyici şablona ulaştığında ikinci aşırı yüklemesi func
görünür olmadığından bu program "Standard two-phase
" yazdırır. eklerseniz /Zc:twoPhase-
, program "Microsoft one-phase
" yazdırır. Çıkış, belirtmediğiniz /permissive-
durumla aynıdır.
Bağımlı adlar , şablon parametresine bağımlı olan adlardır. Bu adların altında /Zc:twoPhase-
da farklı arama davranışları vardır. Uyumluluk modunda, bağımlı adlar şablonun tanımı noktasında bağlı değildir. Bunun yerine, derleyici şablonun örneğini oluşturduğunda bunları arar. Bağımlı işlev adına sahip işlev çağrıları için ad, şablon tanımındaki çağrı sitesinde görünen işlevlere bağlanır. Bağımsız değişkene bağımlı aramadan gelen diğer aşırı yüklemeler, hem şablon tanımının hem de şablon örneği oluşturma noktasında eklenir.
İki aşamalı arama iki bölümden oluşur: Şablon tanımı sırasında bağımlı olmayan adlar için arama ve şablon örneği oluşturma sırasında bağımlı adlar için arama. altında /Zc:twoPhase-
, derleyici bağımsız değişkene bağımlı aramayı nitelenmemiş aramadan ayrı olarak yapmaz. Yani, iki aşamalı arama yapmaz, bu nedenle aşırı yükleme çözümlemesinin sonuçları farklı olabilir.
Aşağıda başka bir örnek verilmiştir:
// zctwophase1.cpp
// To test options, compile by using
// cl /EHsc /W4 zctwophase1.cpp
// cl /EHsc /W4 /permissive- zctwophase1.cpp
// cl /EHsc /W4 /permissive- /Zc:twoPhase- zctwophase1.cpp
#include <cstdio>
void func(long) { std::puts("func(long)"); }
template <typename T> void tfunc(T t) {
func(t);
}
void func(int) { std::puts("func(int)"); }
namespace NS {
struct S {};
void func(S) { std::puts("NS::func(NS::S)"); }
}
int main() {
tfunc(1729);
NS::S s;
tfunc(s);
}
olmadan /permissive-
derlendiğinde bu kod yazdırılır:
func(int)
NS::func(NS::S)
ile /permissive-
derlendiğinde ancak olmadan /Zc:twoPhase-
bu kod yazdırılır:
func(long)
NS::func(NS::S)
hem /Zc:twoPhase-
hem de /permissive-
ile derlendiğinde bu kod yazdırılır:
func(int)
NS::func(NS::S)
altında /permissive-
uyumluluk modunda çağrı tfunc(1729)
aşırı yüklemeye çözümleniyor void func(long)
. altında /Zc:twoPhase-
olduğu gibi aşırı yüklemeye çözümlenmiyorvoid func(int)
. Bunun nedeni, nitelenmemiş func(int)
şablonun tanımından sonra bildirilir ve bağımsız değişkene bağımlı arama aracılığıyla bulunamaz. Ancak void func(S)
bağımsız değişkene bağımlı aramaya katılır, bu nedenle işlev şablonundan sonra bildirildiyse bile çağrısı tfunc(s)
için aşırı yükleme kümesine eklenir.
İki aşamalı uyumluluk için kodunuzu güncelleştirme
Derleyicinin eski sürümleri anahtar sözcükleri template
gerektirmez ve typename
C++ Standard'ın bunları gerektirdiği her yerde. Bu anahtar sözcükler, aramanın ilk aşamasında derleyicilerin bağımlı bir adı nasıl ayrıştırması gerektiğini belirsiz hale getirmek için bazı konumlarda gereklidir. Örneğin:
T::Foo<a || b>(c);
Uyumlu bir derleyici, kapsamında T
bir değişken olarak ayrıştırılırFoo
, yani bu kod, sol işlenen ve b > (c)
sağ işlenen olarak ile T::foo < a
bir mantıksal veya ifadedir. İşlev şablonu olarak kullanmak Foo
istiyorsanız, anahtar sözcüğünü ekleyerek template
bunun bir şablon olduğunu belirtmeniz gerekir:
T::template Foo<a || b>(c);
Visual Studio 2017 sürüm 15.3 ve sonraki sürümlerde, belirtildiğinde /permissive-
ve /Zc:twoPhase-
belirtildiğinde derleyici bu koda template
anahtar sözcüğü olmadan izin verir. Yalnızca sınırlı bir şekilde şablonları ayrıştırdığından, kodu bağımsız değişkeniyle a || b
bir işlev şablonu çağrısı olarak yorumlar. Yukarıdaki kod ilk aşamada ayrıştırılmış değildir. İkinci aşamada, bunun değişken yerine şablon olduğunu T::Foo
söylemek için yeterli bağlam vardır, bu nedenle derleyici anahtar sözcüğün kullanımını zorlamaz.
Bu davranış işlev şablonu gövdelerinde, başlatıcılarda, varsayılan bağımsız değişkenlerde ve noexcept bağımsız değişkenlerinde adlardan önce anahtar sözcüğünü typename
ortadan kaldırarak da görülebilir. Örneğin:
template<typename T>
typename T::TYPE func(typename T::TYPE*)
{
/* typename */ T::TYPE i;
}
İşlev gövdesinde anahtar sözcüğünü typename
kullanmazsanız, bu kod altında /permissive- /Zc:twoPhase-
derlenmiş olur ancak altında tek başına derlemez /permissive-
. anahtar typename
sözcüğü, öğesinin bağımlı olduğunu TYPE
belirtmek için gereklidir. Gövde altında /Zc:twoPhase-
ayrıştırılamadığı için derleyici anahtar sözcüğünü gerektirmez. /permissive-
Uyumluluk modunda, anahtar sözcüğü olmayan typename
kod hatalar oluşturur. Visual Studio 2017 sürüm 15.3 ve sonrasında kodunuzu uyumlu olacak şekilde geçirmek için anahtar sözcüğünü eksik olan yere ekleyin typename
.
Benzer şekilde, şu kod örneğini de göz önünde bulundurun:
template<typename T>
typename T::template X<T>::TYPE func(typename T::TYPE)
{
typename T::/* template */ X<T>::TYPE i;
}
Eski /permissive- /Zc:twoPhase-
derleyicilerde ve altında, derleyici yalnızca 2. satırda anahtar sözcüğünü template
gerektirir. Uyumluluk modunda, derleyici artık bunun bir şablon olduğunu belirtmek için 4. satırda anahtar sözcüğünü T::X<T>
de gerektirirtemplate
. Bu anahtar sözcüğün eksik olduğu kodu arayın ve kodunuzun standarda uygun olmasını sağlamak için kodu sağlayın.
Uyumluluk sorunları hakkında daha fazla bilgi için bkz . Visual Studio'da C++ uyumluluk geliştirmeleri ve Standart olmayan davranış.
Bu derleyici seçeneğini Visual Studio geliştirme ortamında ayarlamak için
Projenin Özellik Sayfaları iletişim kutusunu açın. Ayrıntılar için bkz . Visual Studio'da C++ derleyicisi ve derleme özelliklerini ayarlama.
Yapılandırma Özellikleri>C/C++>Komut Satırı özellik sayfasını seçin.
Ek Seçenekler özelliğini içerecek
/Zc:twoPhase-
şekilde değiştirin ve tamam'ı seçin.