/permissive- (shoda se standardy)
Zadejte režim shody standardů s kompilátorem. Pomocí této možnosti můžete identifikovat a opravit problémy se shodou v kódu, aby byl správný i přenosnější.
Syntax
/permissive-
/permissive
Poznámky
Možnost /permissive- je podporovaná v Visual Studio 2017 a novějších verzích. /permissivese podporuje v Visual Studio 2019 verze 16.8 a novější.
Pomocí možnosti /permissive- kompilátoru můžete určit chování kompilátoru odpovídající standardům. Tato možnost zakáže permisivní chování a nastaví možnosti kompilátoru pro /Zc striktní shodu. V integrovaném vývojovém prostředí tato možnost také podečtení modulu IntelliSense nevyhovujícímu kódu.
Možnost používá podporu shody v aktuální verzi kompilátoru k určení, které jazykové konstrukce /permissive- neodpovídají. Možnost ne určuje, jestli váš kód odpovídá konkrétní verzi standardu C++. Pokud chcete povolit podporu všech implementované kompilátoru pro nejnovější koncept standardu, použijte /std:c++latest možnost . Pokud chcete omezit podporu kompilátoru na aktuálně implementované standardy C++20, použijte /std:c++20 možnost . Pokud chcete omezit podporu kompilátoru na aktuálně implementované standardy C++17, použijte /std:c++17 možnost . Pokud chcete omezit podporu kompilátoru tak, aby více odpovídala standardu C++14, použijte možnost /std:c++14 , která je výchozí.
Možnost se implicitně nastavuje pomocí možnosti /permissive-/std:c++latest počínaje Visual Studio 2019 verze 16.8 a ve verzi 16.11 pomocí /std:c++20 možnosti . /permissive- je vyžadován pro podporu modulů C++20. Váš kód možná nepotřebuje podporu modulů, ale vyžaduje další funkce povolené v rámci /std:c++20 nebo /std:c++latest . Podporu rozšíření Microsoftu můžete explicitně povolit pomocí možnosti /permissive bez koncového pomlčky.
Ve výchozím nastavení je tato možnost nastavená v nových projektech vytvořených /permissive- Visual Studio 2017 verze 15.5 a novější. V dřívějších verzích není ve výchozím nastavení nastavený. Když je tato možnost nastavená, kompilátor generuje diagnostické chyby nebo upozornění, když se v kódu detekují nestandardní jazykové konstrukce. Tyto konstrukce zahrnují některé běžné chyby v kódu před C++11.
Tato možnost je kompatibilní s téměř všemi soubory hlaviček z nejnovějších sad Windows, jako je sada SDK (Software Development Kit) nebo wdk (Windows Driver Kit), počínaje sadou /permissive- Windows Fall Creators SDK (10.0.16299.0). Starší verze sady SDK se nemusí pod z důvodu různé shody /permissive- se zdrojovým kódem zkompilovat. Kompilátor a verze SDK se dodá na různé časové osy vydání, takže existují některé zbývající problémy. Informace o konkrétních problémech se souborem hlaviček najdete Windows následujících potížích s hlavičkou.
Možnost /permissive- nastaví možnosti , a podle /Zc:referenceBinding/Zc:strictStrings/Zc:rvalueCast odpovídajícího chování. Tyto možnosti jsou ve výchozím nastavení nevyhovující chování. Toto chování můžete /Zc přepsat předáním konkrétních možností po na příkazovém /permissive- řádku.
Ve verzích kompilátoru počínaje verzí Visual Studio 2017 verze 15.3 nastaví /permissive- možnost /Zc:ternary . Kompilátor také implementuje více požadavků na dvoufázové vyhledávání názvů. Při nastavení možnosti kompilátor analyzuje definice funkcí a šablon tříd a identifikuje závislé a závislé názvy používané /permissive- v šablonách. V této verzi se provádí pouze analýza závislostí na názvu.
Rozšíření a oblasti jazyka specifické pro prostředí, které standard opustí až do implementace, nejsou ovlivněny /permissive- . Například specifické pro společnost Microsoft , konvence volání a klíčová slova zpracování strukturovaných výjimek a direktivy pragma nebo atributy specifické pro kompilátor nejsou kompilátorem v __declspec/permissive- režimu označeny.
Ne všechny kódy, které odpovídají standardům C++11, C++14 nebo C++17, kompilátor MSVC podporuje ve všech verzích Visual Studio 2017. V závislosti na verzi Visual Studio možnost nemusí detekovat problémy v některých aspektech dvoufázového vyhledávání názvů, svázání nesoučtového odkazu na dočasný objekt, zacházení s inicializací kopírování jako s přímým inicializací, což umožňuje více uživatelem definovaných převodů při inicializaci nebo alternativní tokeny pro logické operátory a další oblasti, které nepodporují /permissive- shodu. Další informace o problémech se shodou v Visual C++ najdete v tématu Nestandardní chování. Pokud chcete z nástroje získat co /permissive- nejvíce, aktualizujte Visual Studio na nejnovější verzi.
Jak opravit kód
Tady je několik příkladů kódu, který se při použití nástroje zjistil jako nevyhovující, společně s navrhovanými /permissive- způsoby, jak tyto problémy vyřešit.
Použití výchozího identifikátoru v nativním kódu
void func(int default); // Error C2321: 'default' is a keyword, and
// cannot be used in this context
Vyhledávání členů v závislém základu
template <typename T>
struct B {
void f();
};
template <typename T>
struct D : public B<T> // B is a dependent base because its type
// depends on the type of T.
{
// One possible fix is to uncomment the following line.
// If this is a type, don't forget the 'typename' keyword.
// using B<T>::f;
void g() {
f(); // error C3861: 'f': identifier not found
// Another fix is to change it to 'this->f();'
}
};
void h() {
D<int> d;
d.g();
}
Použití kvalifikovaných názvů v deklaracích členů
struct A {
void A::f() { } // error C4596: illegal qualified name in member
// declaration.
// Remove redundant 'A::' to fix.
};
Inicializace více členů sjednoceného v inicializátoru členu
union U
{
U()
: i(1), j(1) // error C3442: Initializing multiple members of
// union: 'U::i' and 'U::j'.
// Remove all but one of the initializations to fix.
{}
int i;
int j;
};
Pravidla vyhledávání skrytých přátel
// Example 1
struct S {
friend void f(S *);
};
// Uncomment this declaration to make the hidden friend visible:
// void f(S *); // This declaration makes the hidden friend visible
using type = void (*)(S *);
type p = &f; // error C2065: 'f': undeclared identifier.
// Example 2
struct S {
friend void f(S *);
};
void g() {
// Using nullptr instead of S prevents argument dependent lookup in S
f(nullptr); // error C3861: 'f': identifier not found
S *p = nullptr;
f(p); // Hidden friend now found via argument-dependent lookup.
}
Pravidla vyhledávání skrytých přátel můžete povolit nezávisle na příkazu /permissive pomocí /Zc:hiddenFriend . Pokud chcete, aby se starší verze chování pro vyhledávání skrytých přátel, ale jinak chcete /permissive- chování, použijte /Zc:hiddenFriend- možnost .
Použití vymezených výčtů v mezích polí
enum class Color {
Red, Green, Blue
};
int data[Color::Blue]; // error C3411: 'Color' is not valid as the size
// of an array as it is not an integer type.
// Cast to type size_t or int to fix.
Použití pro každý v nativním kódu
void func() {
int array[] = {1, 2, 30, 40};
for each (int i in array) // error C4496: nonstandard extension
// 'for each' used: replace with
// ranged-for statement:
// for (int i: array)
{
// ...
}
}
Použití atributů ATL
// Example 1
[uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")]
class A {};
// Fix for example 1
class __declspec(uuid("594382D9-44B0-461A-8DE3-E06A3E73C5EB")) B {};
// Example 2
[emitidl];
[module(name="Foo")];
[object, local, uuid("9e66a290-4365-11d2-a997-00c04fa37ddb")]
__interface ICustom {
HRESULT Custom([in] longl, [out, retval] long*pLong);
[local] HRESULT CustomLocal([in] longl, [out, retval] long*pLong);
};
[coclass, appobject, uuid("9e66a294-4365-11d2-a997-00c04fa37ddb")]
class CFoo : public ICustom
{};
// Fix for example 2
// First, create the *.idl file. The vc140.idl generated file can be
// used to automatically obtain a *.idl file for the interfaces with
// annotation. Second, add a midl step to your build system to make
// sure that the C++ interface definitions are outputted.
// Last, adjust your existing code to use ATL directly as shown in
// the atl implementation section.
-- IDL FILE--
import "docobj.idl";
[object, local, uuid(9e66a290-4365-11d2-a997-00c04fa37ddb)]
interface ICustom : IUnknown {
HRESULT Custom([in] longl, [out,retval] long*pLong);
[local] HRESULT CustomLocal([in] longl, [out,retval] long*pLong);
};
[ version(1.0), uuid(29079a2c-5f3f-3325-99a1-3ec9c40988bb) ]
library Foo {
importlib("stdole2.tlb");
importlib("olepro32.dll");
[version(1.0), appobject, uuid(9e66a294-4365-11d2-a997-00c04fa37ddb)]
coclass CFoo { interface ICustom; };
}
-- ATL IMPLEMENTATION--
#include <idl.header.h>
#include <atlbase.h>
class ATL_NO_VTABLE CFooImpl : public ICustom,
public ATL::CComObjectRootEx<CComMultiThreadModel>
{
public:BEGIN_COM_MAP(CFooImpl)
COM_INTERFACE_ENTRY(ICustom)
END_COM_MAP()
};
Nejednoznačné argumenty podmíněného operátoru
Ve verzích kompilátoru před Visual Studio 2017 verze 15.3 kompilátor přijal argumenty podmíněného operátoru (nebo ternární operátor), které jsou standardem považovány za ?: nejednoznačné. V režimu teď kompilátor vydává jednu nebo více diagnostických případů, které se zkompilují /permissive- bez diagnostiky v dřívějších verzích.
Mezi běžné chyby, které mohou být výsledkem této změny, patří:
error C2593: 'operator ?' is ambiguouserror C2679: binary '?': no operator found which takes a right-hand operand of type 'B' (or there is no acceptable conversion)error C2678: binary '?': no operator found which takes a left-hand operand of type 'A' (or there is no acceptable conversion)error C2446: ':': no conversion from 'B' to 'A'
Typický vzor kódu, který může tento problém způsobit, je, když některá třída C poskytuje ne explicitní konstruktor z jiného typu T i operátor převodu, který není explicitní, na typ T. V tomto případě jsou převod druhého argumentu na typ třetího argumentu i převod třetího argumentu na typ druhého argumentu platné převody. Vzhledem k tomu, že obě jsou platné, je podle standardu nejednoznačné.
// Example 1: class that provides conversion to and initialization from some type T
struct A
{
A(int);
operator int() const;
};
extern bool cond;
A a(42);
// Accepted when /Zc:ternary or /permissive- is not used:
auto x = cond ? 7 : a; // A: permissive behavior prefers A(7) over (int)a
// Accepted always:
auto y = cond ? 7 : int(a);
auto z = cond ? A(7) : a;
Tento běžný vzor má důležitou výjimku, když T představuje jeden z typů řetězců ukončených hodnotou null (například , atd.) a skutečný argument pro představuje řetězcový literál odpovídajícího const char *const char16_t *?: typu. C++17 změnil sémantiku z C++14. V důsledku toho je kód v příkladu 2 přijat v rámci a odmítnut v rámci nebo /std:c++14 později při použití nebo /std:c++17/Zc:ternary/permissive- .
// Example 2: exception from the above
struct MyString
{
MyString(const char* s = "") noexcept; // from char*
operator const char* () const noexcept; // to char*
};
extern bool cond;
MyString s;
// Using /std:c++14, /permissive- or /Zc:ternary behavior
// is to prefer MyString("A") over (const char*)s
// but under /std:c++17 this line causes error C2445:
auto x = cond ? "A" : s;
// You can use a static_cast to resolve the ambiguity:
auto y = cond ? "A" : static_cast<const char*>(s);
Dalším případem, kdy se vidíte chyby, je v podmíněných operátorech s jedním argumentem typu void . Tento případ může být běžný v makrech jako ASSERT.
// Example 3: void arguments
void myassert(const char* text, const char* file, int line);
// Accepted when /Zc:ternary or /permissive- is not used:
#define ASSERT_A(ex) (void)((ex) ? 1 : myassert(#ex, __FILE__, __LINE__))
// Accepted always:
#define ASSERT_B(ex) (void)((ex) ? void() : myassert(#ex, __FILE__, __LINE__))
V metaprogramování šablon se mohou zobrazit také chyby, kdy se v a mohou měnit typy výsledků podmíněného /Zc:ternary/permissive- operátoru. Jedním ze způsob, jak tento problém vyřešit, je std::remove_reference použít u výsledného typu.
// Example 4: different result types
extern bool cond;
extern int count;
char a = 'A';
const char b = 'B';
decltype(auto) x = cond ? a : b; // char without, const char& with /Zc:ternary
const char (&z)[2] = count > 3 ? "A" : "B"; // const char* without /Zc:ternary
Dvoufázové vyhledávání názvů
Při nastavení možnosti kompilátor analyzuje definice funkcí a šablon tříd a identifikuje závislé a závislé názvy používané v šablonách podle potřeby pro dvoufázové /permissive- vyhledávání názvů. V Visual Studio 2017 verze 15.3 se provádí analýza závislostí na názvu. Konkrétně nezávisející názvy, které nejsou deklarovány v kontextu definice šablony, způsobují diagnostickou zprávu podle požadavků standardů ISO C++. V Visual Studio 2017 verze 15.7 se také provádí vazba nesouvisející názvy, které vyžadují vyhledávání závislé na argumentu v kontextu definice.
// dependent base
struct B {
void g() {}
};
template<typename T>
struct D : T {
void f() {
// The call to g was incorrectly allowed in VS2017:
g(); // Now under /permissive-: C3861
// Possible fixes:
// this->g();
// T::g();
}
};
int main()
{
D<B> d;
d.f();
}
Pokud chcete starší verzi chování pro dvoufázové vyhledávání, ale jinak chcete /permissive- chování, přidejte /Zc:twoPhase- možnost .
Windows s hlavičkou
Tato možnost je příliš striktní pro verze sad Windows Kit před /permissive- Windows Fall Creators Update SDK (10.0.16299.0) nebo wdk (Windows Driver Kit) verze 1709. Doporučujeme aktualizovat na nejnovější verze sad Windows Kit, abyste je mohli použít v Windows /permissive- kódu ovladače zařízení.
Některé soubory hlaviček v sadě Windows Update SDK z dubna 2018 (10.0.17134.0), sadě Windows Fall Creators Update SDK (10.0.16299.0) nebo sadě WDK (Windows Driver Kit) 1709 mají stále problémy, které je nekompatibilní s používáním /permissive- . Pokud chcete tyto problémy obvyřešit, doporučujeme omezit použití těchto hlaviček pouze na soubory zdrojového kódu, které je vyžadují, a odebrat možnost při kompilaci těchto konkrétních souborů /permissive- zdrojového kódu.
Tyto hlavičky WinRT WRL vydané v sadě sdk aktualizace Windows. dubna 2018 (10.0.17134.0) nejsou pomocí /permissive- čisté. Pokud chcete tyto problémy obvyřešit, při práci s těmito hlavičkami buď nepoužívejte , nebo použijte s /permissive-/permissive-/Zc:twoPhase- :
Problémy v souboru winrt/wrl/async.h
C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\winrt\wrl\async.h(483): error C3861: 'TraceDelegateAssigned': identifier not found C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\winrt\wrl\async.h(491): error C3861: 'CheckValidStateForDelegateCall': identifier not found C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\winrt\wrl\async.h(509): error C3861: 'TraceProgressNotificationStart': identifier not found C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\winrt\wrl\async.h(513): error C3861: 'TraceProgressNotificationComplete': identifier not foundProblém v souboru winrt/wrl/implements.h
C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\winrt\wrl\implements.h(2086): error C2039: 'SetStrongReference': is not a member of 'Microsoft::WRL::Details::WeakReferenceImpl'
Tyto hlavičky uživatelského režimu vydané v sadě WINDOWS Update SDK z dubna 2018 (10.0.17134.0) nejsou pomocí /permissive- čisté. Pokud chcete tyto problémy obvyřešit, nepoužívejte při práci /permissive- s těmito hlavičkami:
Problémy v um/Tune.h
C:\ProgramFiles(x86)\Windows Kits\10\include\10.0.17134.0\um\tune.h(139): error C3861: 'Release': identifier not found C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um\tune.h(559): error C3861: 'Release': identifier not found C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um\tune.h(1240): error C3861: 'Release': identifier not found C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um\tune.h(1240): note: 'Release': function declaration must be available as none of the arguments depend on a template parameterProblém v um/spddštinalp.h
C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um\spddkhlp.h(759): error C3861: 'pNode': identifier not foundProblémy v um/refptrco.h
C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um\refptrco.h(179): error C2760: syntax error: unexpected token 'identifier', expected 'type specifier' C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um\refptrco.h(342): error C2760: syntax error: unexpected token 'identifier', expected 'type specifier' C:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um\refptrco.h(395): error C2760: syntax error: unexpected token 'identifier', expected 'type specifier'
Tyto problémy jsou specifické pro hlavičky uživatelského režimu v Windows Fall Creators Update SDK (10.0.16299.0):
Problém v um/Query.h
Při použití
/permissive-přepínače kompilátoru se struktura nezkompiluje kvůlitagRESTRICTIONčlenu case(RTOr) nebo.struct tagRESTRICTION { ULONG rt; ULONG weight; /* [switch_is][switch_type] */ union _URes { /* [case()] */ NODERESTRICTION ar; /* [case()] */ NODERESTRICTION or; // error C2059: syntax error: '||' /* [case()] */ NODERESTRICTION pxr; /* [case()] */ VECTORRESTRICTION vr; /* [case()] */ NOTRESTRICTION nr; /* [case()] */ CONTENTRESTRICTION cr; /* [case()] */ NATLANGUAGERESTRICTION nlr; /* [case()] */ PROPERTYRESTRICTION pr; /* [default] */ /* Empty union arm */ } res; };Pokud chcete tento problém vyřešit, zkompilujte soubory, které obsahují Query.h bez
/permissive-možnosti .Problém v um/cellularapi_oem.h
Při použití
/permissive-přepínače kompilátoru dopředná deklaraceenum UICCDATASTOREACCESSMODEzpůsobí upozornění:typedef enum UICCDATASTOREACCESSMODE UICCDATASTOREACCESSMODE; // C4471Dopředná deklarace výčtu bez oborů je rozšíření společnosti Microsoft. Pokud chcete tento problém vyřešit, zkompilujte soubory, které zahrnují cellularapi_oem.h bez možnosti , nebo použijte možnost upozornění
/permissive-/wdC4471.Problém v um/omscript.h
V jazyce C++03 je převod z řetězcového literálu na BSTR (což je definice typedef pro "wchar_t *") zastaralý, ale povolený. V jazyce C++11 už převod není povolený.
virtual /* [id] */ HRESULT STDMETHODCALLTYPE setExpression( /* [in] */ __RPC__in BSTR propname, /* [in] */ __RPC__in BSTR expression, /* [in][defaultvalue] */ __RPC__in BSTR language = L"") = 0; // C2440Pokud chcete tento problém vyřešit, zkompilujte soubory, které obsahují omscript.h bez možnosti
/permissive-, nebo použijte místo toho/Zc:strictStrings-.
Nastavení tohoto parametru kompilátoru ve vývojovém prostředí Visual Studio
v Visual Studio 2017 verze 15,5 a novější použijte tento postup:
Otevřete dialogové okno stránky vlastností projektu.
Vyberte stránku vlastností Konfiguracejazyka C/C++ .
Změňte hodnotu vlastnosti Režim odpovídání na Ano (/Permissive-). Změny uložte kliknutím na OK nebo použít .
v části verze před Visual Studio 2017 verze 15,5 použijte tento postup:
Otevřete dialogové okno stránky vlastností projektu.
Vyberte stránku vlastností Konfiguracepříkazového řádku C/C++.
Do pole Další možnosti zadejte možnost kompilátoru /Permissive- . Změny uložte kliknutím na OK nebo použít .
Programové nastavení tohoto parametru kompilátoru
- Viz AdditionalOptions.
Viz také
možnosti kompilátoru MSVC
MSVC syntaxe Command-Line kompilátoru