Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Met de /Zc:twoPhase- optie onder /permissive-geeft u aan dat de compiler het oorspronkelijke, niet-conforme Microsoft C++-compilergedrag moet gebruiken om klassesjablonen en functiesjablonen te parseren en instantiëren.
Syntaxis
/Zc:twoPhase-
Opmerkingen
Visual Studio 2017 versie 15.3 en hoger: Onder /permissive-, maakt de compiler gebruik van tweefasige naamzoekactie voor sjabloonnaamomzetting. Als u ook opgeeft /Zc:twoPhase-, wordt de compiler teruggezet naar de vorige niet-conforme klassesjabloon en functiesjabloon naamomzetting en vervangingsgedrag. Wanneer /permissive- niet is opgegeven, is het niet-conforme gedrag de standaardinstelling.
De Windows SDK-headerbestanden in versie 10.0.15063.0 (Makersupdate of RS2) en eerder werken niet in de nalevingsmodus.
/Zc:twoPhase- is vereist voor het compileren van code voor deze SDK-versies wanneer u gebruikt /permissive-. Versies van de Windows SDK vanaf versie 10.0.15254.0 (Fall Creators Update of RS3) werken correct in de nalevingsmodus. Ze hebben de /Zc:twoPhase- optie niet nodig.
Gebruik /Zc:twoPhase- deze optie als uw code vereist dat het oude gedrag correct wordt gecompileerd. Overweeg om uw code bij te werken om aan de standaard te voldoen.
Compilergedrag onder /Zc:twoPhase-
Standaard of in Visual Studio 2017 versie 15.3 en hoger wanneer u beide /permissive- opgeeft en /Zc:twoPhase-, gebruikt de compiler dit gedrag:
Hiermee worden alleen de sjabloondeclaratie, het hoofd van de klasse en de basisklasselijst geparseerd. De hoofdtekst van de sjabloon wordt vastgelegd als een tokenstroom. Er worden geen functieteksten, initialisatiefuncties, standaardargumenten of noexcept-argumenten geparseerd. De klassesjabloon wordt pseudo geïnstantieerd op een voorlopig type om te controleren of de declaraties in de klassesjabloon juist zijn. Houd rekening met deze klassesjabloon:
template <typename T> class Derived : public Base<T> { ... }De sjabloondeclaratie,
template <typename T>het hoofd van de klasseclass Deriveden de lijstpublic Base<T>met basisklassen worden geparseerd, maar de hoofdtekst van de sjabloon wordt vastgelegd als een tokenstroom.Wanneer een functiesjabloon wordt geparseerd, parseert de compiler alleen de functiehandtekening. De hoofdtekst van de functie wordt nooit geparseerd. In plaats daarvan wordt het vastgelegd als een tokenstroom.
Als de hoofdtekst van de sjabloon syntaxisfouten bevat, maar de sjabloon nooit wordt geïnstantieerd, worden de fouten niet door de compiler vastgesteld.
Een ander effect van dit gedrag is in overbelastingsresolutie. Niet-standaardgedrag treedt op vanwege de manier waarop de tokenstroom wordt uitgebreid op de site van instantiëring. Symbolen die niet zichtbaar waren in de sjabloondeclaratie, zijn mogelijk zichtbaar op het moment van instantiëring. Dat betekent dat ze kunnen deelnemen aan overbelastingsresolutie. Mogelijk vindt u dat sjablonen gedrag wijzigen op basis van code die niet zichtbaar was in de sjabloondefinitie, in tegenstelling tot de standaard.
Denk bijvoorbeeld aan deze code:
// 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);
}
Hier ziet u de uitvoer wanneer u de standaardmodus, de nalevingsmodus en de nalevingsmodus gebruikt met /Zc:twoPhase- compileropties:
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
Wanneer het programma is gecompileerd in de conformantiemodus onder /permissive-, wordt '' afgedruktStandard two-phase, omdat de tweede overbelasting func niet zichtbaar is wanneer de compiler de sjabloon bereikt. Als u toevoegt /Zc:twoPhase-, drukt het programma 'Microsoft one-phase' af. De uitvoer is hetzelfde als wanneer u niet opgeeft /permissive-.
Afhankelijke namen zijn namen die afhankelijk zijn van een sjabloonparameter. Deze namen hebben opzoekgedrag dat ook verschilt onder /Zc:twoPhase-. In de nalevingsmodus zijn afhankelijke namen niet gebonden aan het punt van de definitie van de sjabloon. In plaats daarvan zoekt de compiler deze op wanneer de sjabloon wordt geïnstitueert. Voor functie-aanroepen met een afhankelijke functienaam wordt de naam gebonden aan functies die zichtbaar zijn op de aanroepsite in de sjabloondefinitie. Andere overbelastingen van argumentafhankelijke zoekopdrachten worden toegevoegd, zowel op het punt van de sjabloondefinitie als op het moment van sjabloon-instantiëring.
Opzoeken in twee fasen bestaat uit twee delen: de zoekactie voor niet-afhankelijke namen tijdens de sjabloondefinitie en de zoekactie voor afhankelijke namen tijdens het instantiëring van de sjabloon. Onder /Zc:twoPhase-, de compiler voert geen argumentafhankelijke zoekactie afzonderlijk uit van niet-gekwalificeerde zoekactie. Dat wil gezegd, het doet geen zoekactie in twee fasen, dus de resultaten van overbelastingsresolutie kunnen afwijken.
Hier volgt nog een voorbeeld:
// 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);
}
Wanneer deze code wordt gecompileerd zonder /permissive-, wordt het volgende afgedrukt:
func(int)
NS::func(NS::S)
Wanneer deze code is gecompileerd met /permissive-, maar zonder /Zc:twoPhase-, wordt de volgende code afgedrukt:
func(long)
NS::func(NS::S)
Wanneer deze code is gecompileerd met beide /permissive- en /Zc:twoPhase-, wordt deze code afgedrukt:
func(int)
NS::func(NS::S)
In de conformantiemodus onder /permissive-, wordt de aanroep tfunc(1729) omgezet in de void func(long) overbelasting. Het lost niet op tot de void func(int) overbelasting, zoals onder /Zc:twoPhase-. De reden hiervoor is dat de niet-gekwalificeerde wordt gedeclareerd func(int) na de definitie van de sjabloon en niet wordt gevonden via argumentafhankelijke zoekactie. Maar void func(S) neemt wel deel aan argumentafhankelijke zoekactie, dus deze wordt toegevoegd aan de overbelastingsset voor de aanroep tfunc(s), ook al wordt deze gedeclareerd na de functiesjabloon.
Uw code bijwerken voor naleving in twee fasen
Voor oudere versies van de compiler zijn de trefwoorden template niet vereist en typename overal waar de C++ Standard deze nodig heeft. Deze trefwoorden zijn in sommige posities nodig om te bepalen hoe compilers een afhankelijke naam moeten parseren tijdens de eerste fase van de zoekactie. Voorbeeld:
T::Foo<a || b>(c);
Een conforme compiler parseert Foo als een variabele in het bereik van T, wat betekent dat deze code een logische of expressie is met T::foo < a als de linkeroperand en b > (c) als de rechteroperand. Als u een functiesjabloon wilt gebruiken Foo , moet u aangeven dat het een sjabloon is door het template trefwoord toe te voegen:
T::template Foo<a || b>(c);
In versies Visual Studio 2017 versie 15.3 en hoger, wanneer /permissive- en /Zc:twoPhase- worden opgegeven, staat de compiler deze code toe zonder het template trefwoord. De code wordt geïnterpreteerd als een aanroep van een functiesjabloon met een argument van a || b, omdat deze alleen sjablonen op beperkte wijze parseert. De bovenstaande code wordt helemaal niet geparseerd in de eerste fase. Tijdens de tweede fase is er voldoende context om te vertellen dat T::Foo het een sjabloon is in plaats van een variabele, dus de compiler dwingt het gebruik van het trefwoord niet af.
Dit gedrag kan ook worden gezien door het trefwoord typename voor namen in functiesjabloonteksten, initialisatiefuncties, standaardargumenten en noexcept-argumenten te elimineren. Voorbeeld:
template<typename T>
typename T::TYPE func(typename T::TYPE*)
{
/* typename */ T::TYPE i;
}
Als u het trefwoord typename niet in de hoofdtekst van de functie gebruikt, wordt deze code gecompileerd onder /permissive- /Zc:twoPhase-, maar niet alleen /permissive- . Het typename trefwoord is vereist om aan te geven dat het TYPE afhankelijk is. Omdat de hoofdtekst niet wordt geparseerd onder /Zc:twoPhase-, is het trefwoord niet vereist voor de compiler. In /permissive- de nalevingsmodus genereert code zonder het typename trefwoord fouten. Als u uw code wilt migreren naar overeenstemming in Visual Studio 2017 versie 15.3 en hoger, voegt u het typename trefwoord in waar deze ontbreekt.
Houd ook rekening met dit codevoorbeeld:
template<typename T>
typename T::template X<T>::TYPE func(typename T::TYPE)
{
typename T::/* template */ X<T>::TYPE i;
}
Onder /permissive- /Zc:twoPhase- en in oudere compilers vereist de compiler alleen het template trefwoord op regel 2. In de nalevingsmodus vereist de compiler nu ook het template trefwoord op regel 4 om aan te geven dat T::X<T> dit een sjabloon is. Zoek naar code die dit trefwoord ontbreekt en geef deze op om ervoor te zorgen dat uw code voldoet aan de standaard.
Zie C ++ conformanceverbeteringen in Visual Studio en niet-standaardgedrag voor meer informatie over nalevingsproblemen.
Deze compileroptie instellen in de Ontwikkelomgeving van Visual Studio
Open het dialoogvenster eigenschappenpagina's van het project. Zie C++-compiler instellen en eigenschappen bouwen in Visual Studiovoor meer informatie.
Selecteer de eigenschappenpagina configuratie-eigenschappen>C/C++>opdrachtregel.
Wijzig de eigenschap Aanvullende opties om op te nemen
/Zc:twoPhase-en kies vervolgens OK.