Miglioramenti della conformità di C++ in Visual Studio 2017 versioni 15.0, 15.3 e 15.5.C++ conformance improvements in Visual Studio 2017 versions 15.0, 15.3 and 15.5.

Con il supporto per la parola chiave constexpr generalizzata e NSDMI per le aggregazioni, il compilatore è ora completo per le funzionalità aggiunte nello Standard C++14.With support for generalized constexpr and NSDMI for aggregates, the compiler is now complete for features added in the C++14 Standard. Si noti che il compilatore manca ancora di alcune funzionalità relative agli standard C++11 e C++98.Note that the compiler still lacks a few features from the C++11 and C++98 Standards. Vedere Visual C++ Language Conformance (Conformità al linguaggio Visual C++) per una tabella che mostra lo stato corrente del compilatore.See Visual C++ Language Conformance for a table that shows the current state of the compiler.

C++11C++11

Supporto per l'espressione SFINAE in altre librerie Il compilatore Visual C++ continua a migliorare il supporto per l'espressione SFINAE, che è necessario per la deduzione e la sostituzione dell'argomento del modello dove le espressioni decltype e constexpr possono apparire come parametri del modello.Expression SFINAE support in more libraries The Visual C++ compiler continues to improve its support for expression SFINAE, which is required for template argument deduction and substitution where decltype and constexpr expressions may appear as template parameters. Per altre informazioni, vedere il blog relativo ai miglioramenti dell'espressione SFINAE in Visual Studio 2017 RC.For more information, see Expression SFINAE improvements in Visual Studio 2017 RC.

C++ 14C++ 14

NSDMI per gli aggregati Un aggregato è una matrice o una classe che non ha costruttori specificati dall'utente, membri dati non statici privati o protetti, classi di base né funzioni virtuali.NSDMI for Aggregates An aggregate is an array or a class with no user-provided constructor, no private or protected non-static data members, no base classes, and no virtual functions. A partire da C++14 gli aggregati possono contenere inizializzatori di membro.Beginning in C++14 aggregates may contain member initializers. Per altre informazioni, vedere l'argomento relativo a inizializzatori di membro e aggregati.For more information, see Member initializers and aggregates.

Constexpr estesa Le espressioni dichiarate come constexpr ora possono contenere determinati tipi di dichiarazioni, istruzioni if e switch, istruzioni loop e modifica di oggetti la cui durata è iniziata all'interno della valutazione dell'espressione constexpr.Extended constexpr Expressions declared as constexpr are now allowed to contain certain kinds of declarations, if and switch statements, loop statements, and mutation of objects whose lifetime began within the constexpr expression evaluation. Inoltre, non è più un requisito che una funzione membro non statica constexpr sia const in modo implicito.Also, there is no longer a requirement that a constexpr non-static member function be implicitly const. Per altre informazioni, vedere l'argomento relativo alla riduzione dei vincoli per le funzioni constexpr.For more information, see Relaxing constraints on constexpr functions.

C++17C++17

Forma concisa di static_assert (disponibile con /std:c++17) In C++17 il parametro del messaggio per static_assert è facoltativo.Terse static_assert (available with /std:c++17) In C++17 the message parameter for static_assert is optional. Per altre informazioni, vedere il documento relativo all'estensione di static_assert, v2.For more information, see Extending static_assert, v2.

Attributo [[fallthrough]] (disponibile con /std:c++17) L'attributo [[fallthrough]] può essere usato nel contesto di istruzioni switch per suggerire al compilatore che il comportamento del fallthrough è previsto.[[fallthrough]] attribute (available with /std:c++17) The [[fallthrough]] attribute can be used in the context of switch statements as a hint to the compiler that the fall-through behavior is intended. Ciò impedisce al compilatore di emettere avvisi in tali casi.This prevents the compiler from issuing warnings in such cases. Per altre informazioni, vedere il documento sulla definizione per l'attributo [[fallthrough]].For more information, see Wording for [[fallthrough]] attribute.

Cicli for generalizzati basati su intervallo (non sono necessarie opzioni del compilatore) I cicli for basati su intervallo non richiedono più che begin() ed end() restituiscano oggetti dello stesso tipo.Generalized range-based for loops (no compiler switch required) Range-based for loops no longer require that begin() and end() return objects of the same type. Ciò consente a end() di restituire un sentinel usato dagli intervalli in range-v3 e dalla specifica tecnica sugli intervalli, completa, ma non abbastanza pubblicata.This enables end() to return a sentinel as used by ranges in range-v3 and the completed-but-not-quite-published Ranges Technical Specification. Per altre informazioni, vedere Generalizing the Range-Based For Loop (Generalizzazione del ciclo for basato su intervallo).For more information, see Generalizing the Range-Based For Loop.

Miglioramenti in Visual Studio 2017 versione 15.3 Improvements in Visual Studio 2017 version 15.3

Espressioni lambda constexpr È ora possibile usare espressioni lambda nelle espressioni costanti.constexpr lambdas Lambda expressions may now be used in constant expressions. Per altre informazioni, vedere Constexpr Lambda (Espressione lambda constexpr).For more information, see Constexpr Lambda.

if constexpr nei modelli di funzione Un modello di funzione può contenere istruzioni if constexpr per abilitare il branching in fase di compilazione.if constexpr in function templates A function template may contain if constexpr statements to enable compile-time branching. Per altre informazioni, vedere if constexpr.For more information, see if constexpr.

Istruzioni di selezione con inizializzatori Un'istruzione if può includere un inizializzatore che introduce una variabile nell'ambito del blocco all'interno dell'istruzione stessa.Selection statements with initializers An if statement may include an initializer that introduces a variable at block scope within the statement itself. Per altre informazioni, vedere Selection statements with initializer (Istruzioni di selezione con inizializzatore).For more information, see Selection statements with initializer.

Attributi [[maybe_unused]] e [[nodiscard]] Nuovi attributi per ignorare gli avvisi quando non viene usata un'entità oppure per creare un avviso se il valore restituito di una chiamata di funzione viene rimosso.[[maybe_unused]] and [[nodiscard]] attributes New attributes to silence warnings when an entity is not used, or to create a warning if the return value of a function call is discarded. Per altre informazioni, vedere Wording for maybe_unused attribute (Formulazione per l'attributo maybe_unused) e Proposal of unused,nodiscard and fallthrough attributes (Proposta per gli attributi unused, nodiscard e fallthrough).For more information, see Wording for maybe_unused attribute and Proposal of unused,nodiscard and fallthrough attributes.

Uso degli spazi dei nomi degli attributi senza ripetizioni Nuova sintassi per consentite un solo identificatore di spazio dei nomi in un elenco di attributi.Using attribute namespaces without repetition New syntax to enable only a single namespace identifier in an attribute list. Per altre informazioni, vedere Attributes in C++ (Attributi in C++).For more information, see Attributes in C++.

Binding strutturati In una singola dichiarazione, è ora possibile archiviare un valore con i nomi singoli dei relativi componenti, quando il valore è una matrice, std::tuple o std::pair oppure tutti i membri dati sono non statici e pubblici.Structured bindings It is now possible in a single declaration to store a value with individual names for its components, when the value is an array, a std::tuple or std::pair, or has all public non-static data members. Per altre informazioni, vedere Structured Bindings (Binding strutturati).For more information, see Structured Bindings.

Regole di costruzione per i valori di classi Enum È ora disponibile una conversione implicita (non verso un tipo di dati più piccolo) dal tipo sottostante di un'enumerazione con ambito all'enumerazione stessa, quando la definizione dell'enumerazione non introduce alcun enumeratore e l'origine usa la sintassi di inizializzazione elenco.Construction rules for enum class values There is now an implicit/non-narrowing conversion from a scoped enumeration's underlying type to the enumeration itself, when its definition introduces no enumerator and the source uses a list-initialization syntax. Per altre informazioni, vedere Construction Rules for enum class Values (Regole di costruzione per i valori di classe Enum).For more information, see Construction Rules for enum class Values .

Acquisizione di *this per valore L'oggetto "*this" in un'espressione lambda può ora essere acquisito per valore.Capturing *this by value The "*this" object in a lambda expression may now be captured by value. Ciò rende possibili scenari in cui l'espressione lambda viene richiamata in operazioni parallele e asincrone, in particolare nelle architetture di computer più recenti.This enables scenarios in which the lambda will be invoked in parallel and asynchronous operations, especially on newer machine architectures. Per altre informazioni, vedere Lambda Capture of *this by Value as [=,*this] (Acquisizione di this per valore come [=,this] nelle espressioni lambda).For more information, see Lambda Capture of *this by Value as [=,*this].

Rimozione di operator++ per bool operator++ non è più supportato per i tipi bool.Removing operator++ for bool operator++ is no longer supported on bool types. Per altre informazioni, vedere Remove Deprecated operator++(bool) (Rimozione di operator++(bool) deprecato).For more information, see Remove Deprecated operator++(bool).

Rimozione della parola chiave "register" deprecata La parola chiave register, precedentemente deprecata e ignorata dal compilatore Visual C++, è stata ora rimossa dal linguaggio.Removing deprecated "register" keyword The register keyword, previously deprecated (and ignored by the Visual C++ compiler), is now removed from the language. Per altre informazioni, vedere Remove Deprecated Use of the register Keyword (Rimozione della parola chiave register per uso deprecato).For more information, see Remove Deprecated Use of the register Keyword.

Per l'elenco completo dei miglioramenti apportati alla conformità fino a Visual Studio 2015 Update 3, vedere Visual C++: novità dalla versione 2003 alla 2015.For the complete list of conformance improvements up through Visual Studio 2015, Update 3, see Visual C++ What's New 2003 through 2015.

Miglioramenti in Visual Studio 2017 versione 15.5 Improvements in Visual Studio 2017 version 15.5

Le funzionalità contrassegnate con [14] sono disponibili senza condizioni anche nella modalità /std:c++14.Features marked with [14] are available unconditionally even in /std:c++14 mode.

Nuova opzione del compilatore per extern constexpr Nelle versioni precedenti di Visual Studio il compilatore assegna sempre un collegamento interno della variabile constexpr anche quando la variabile è contrassegnata come extern.New compiler switch for extern constexpr In earlier versions of Visual Studio, the compiler always gave a constexpr variable internal linkage even when the variable was marked extern. In Visual Studio 2017 versione 15.5 una nuova opzione del compilatore, /Zc:externConstexpr, abilita il comportamento corretto conforme agli standard.In Visual Studio 2017 version 15.5, a new compiler switch, /Zc:externConstexpr, enables correct standards-conforming behavior. Per altre informazioni, vedere Collegamento extern constexpr.For more information, see extern constexpr linkage.

Rimozione delle specifiche di eccezione dinamiche: P0003R5.Removing Dynamic Exception Specifications: P0003R5. Le specifiche di eccezione dinamiche sono deprecate in C++11.Dynamic exception specifications were deprecated in C++11. La funzionalità è stata rimossa da C++17, ma la specifica (ancora) deprecata throw() viene conservata esclusivamente come alias per noexcept(true).the feature is removed from C++17, but the (still) deprecated throw() specification is retained strictly as an alias for noexcept(true). Per altre informazioni, vedere Dynamic exception specification removal and noexcept (Rimozione della specifica di eccezione dinamica e noexcept).For more information, see Dynamic exception specification removal and noexcept.

not_fn(): P0005R4 è un sostituzione di not1 e not2.not_fn() : P0005R4 is a replacement of not1 and not2.

Ridefinizione di enable_shared_from_this: P0033R1 enable_shared_from_this è stato aggiunto in C++11.Rewording enable_shared_from_this: P0033R1 enable_shared_from_this was added in C++11. Lo standard C++17 aggiorna la specifica per gestire meglio determinati casi limite.The C++17 Standard updates the specification to better handle certain corner cases. [14][14]

Splicing mappe e set: P0083R3.Splicing Maps And Sets: P0083R3. Questa funzionalità consente l'estrazione dei nodi dai contenitori associativi (ad esempio, map, set, unordered_map, unordered_set) che possono quindi essere modificati e nuovamente inseriti nello stesso contenitore o in un contenitore diverso che usa lo stesso tipo di nodo.This feature enables extraction of nodes from associative containers (e.g., map, set, unordered_map, unordered_set) which can then be modified and inserted back into the same container or a different container that uses the same node type. Un caso d'uso comune è l'estrazione di un nodo da std::map, la modifica della chiave e il reinserimento.(A common use case is to extract a node from a std::map, change the key, and reinsert.)

Deprecazione di parti superflue della libreria: P0174R2.Deprecating Vestigial Library Parts: P0174R2. Diverse funzionalità della libreria standard C++ sono state sostituite da funzionalità più recenti nel corso degli anni oppure si sono rivelate poco utili o problematiche.Several features of the C++ Standard library have been superceded by newer features over the years, or else have been found to be not very useful or to be problematic. Queste funzionalità sono ufficialmente deprecate in C++ 17.These features are officially deprecated in C++17.

Rimozione supporto allocatore in std::function: P0302R1.Removing Allocator Support In std::function: P0302R1. Prima di C++17 il modello di classe std::function aveva diversi costruttori che accettavano un argomento allocatore.Prior to C++17 the class template std::function had several constructors that took an allocator argument. L'uso di allocatori in questo contesto era tuttavia problematico e la semantica non era chiara.However, the use of allocators in this context was problematic, and the semantics were unclear. Questi costruttori sono stati quindi rimossi.Therefore these contructors were removed.

Correzioni per not_fn(): P0358R1.Fixes for not_fn(): P0358R1. La nuova formulazione per std::not_fn fornisce il supporto della propagazione della categoria di valori in caso di chiamata al wrapper.New wording for std::not_fn provides support of propagation of value category in case of wrapper invocation.

shared_ptr<T[]>, shared_ptr<T[N]>: P0414R2.shared_ptr<T[]>, shared_ptr<T[N]>: P0414R2. Merge delle modifiche shared_ptr da Library Fundamentals a C++17.Merging shared_ptr changes from Library Fundamentals to C++17. [14][14]

Correzione shared_ptr per matrici: P0497R0.Fixing shared_ptr for Arrays: P0497R0. Correzioni al supporto shared_ptr per matrici.Fixes to shared_ptr support for arrays. [14][14]

Chiarimento di insert_return_type: P0508R0.Clarifying insert_return_type: P0508R0. I contenitori associativi con chiavi univoche e i contenitori non ordinati con chiavi univoche hanno una funzione membro insert che restituisce un tipo annidato insert_return_type.The associative containers with unique keys, and the unordered containers with unique keys have a member function insert that returns a nested type insert_return_type. Tale tipo restituito è ora definito come specializzazione di un tipo con parametri negli elementi Iterator e NodeType del contenitore.That return type is now defined as a specialization of a type that is parameterized on the Iterator and NodeType of the container.

Variabili inline per STL: P0607R0.Inline Variables For The STL: P0607R0.

Funzionalità Annex D deprecate Annex D dello standard C++ contiene tutte le funzionalità deprecate, incluse shared_ptr::unique(), <codecvt> e namespace std::tr1.Annex D features deprecated Annex D of the C++ standard contains all the features that have been deprecated, including shared_ptr::unique(), <codecvt>, and namespace std::tr1. Quando l'opzione del compilatore /std:c++17 è impostata, quasi tutte le funzionalità della libreria standard in Annex D vengono contrassegnate come deprecate.When the /std:c++17 compiler switch is set, almost all the Standard Library features in Annex D are marked as deprecated. Per altre informazioni, vedere Le funzionalità della libreria standard in Annex D vengono contrassegnate come deprecate.For more information, see Standard Library features in Annex D are marked as deprecated.

Lo spazio dei nomi std::tr2::sys in <experimental/filesystem> crea un avviso di deprecazione in /std:c++14 per impostazione predefinita e ora viene rimosso in /std:c++17 per impostazione predefinita.The std::tr2::sys namespace in <experimental/filesystem> now emits a deprecation warning under /std:c++14 by default, and is now removed under /std:c++17 by default.

La conformità negli elementi iostream è stata migliorata evitando un'estensione non standard (specializzazioni esplicite in-class).Improved conformance in iostreams by avoiding a non-Standard extension (in-class explicit specializations).

La libreria standard ora usa modelli di variabile internamente.The Standard Library now uses variable templates internally.

La libreria standard è stata aggiornata in risposta alle modifiche del compilatore C++17, incluse l'aggiunta di noexcept nel sistema dei tipi e la rimozione delle specifiche di eccezione dinamiche.The Standard Library has been updated in response to C++17 compiler changes, including the addition of noexcept in the type system and the removal of dynamic-exception-specifications.

Correzioni di bug in Visual Studio versioni 15.0, 15.3 e 15.5Bug fixes in Visual Studio versions 15.0, 15.3, and 15.5

Copy-list-initializationCopy-list-initialization

Visual Studio 2017 genera correttamente errori del compilatore relativi alla creazione di oggetti con gli elenchi di inizializzatori che non venivano rilevati in Visual Studio 2015 e potevano causare un arresto anomalo o un comportamento non definito in fase di esecuzione.Visual Studio 2017 correctly raises compiler errors related to object creation using initializer lists that were not caught in Visual Studio 2015 and could lead to crashes or undefined runtime behavior. In base a N4594 13.3.1.7p1, in copy-list-initialization, il compilatore deve prendere in considerazione un costruttore esplicito per la risoluzione dell'overload, ma deve generare un errore se viene scelto tale overload.As per N4594 13.3.1.7p1, in copy-list-initialization, the compiler is required to consider an explicit constructor for overload resolution, but must raise an error if that overload is actually chosen.

I seguenti due esempi vengono compilati in Visual Studio 2015 ma non in Visual Studio 2017.The following two examples compile in Visual Studio 2015 but not in Visual Studio 2017.

struct A
{
    explicit A(int) {} 
    A(double) {}
};

int main()
{
    A a1 = { 1 }; // error C3445: copy-list-initialization of 'A' cannot use an explicit constructor
    const A& a2 = { 1 }; // error C2440: 'initializing': cannot convert from 'int' to 'const A &'

}

Per correggere l'errore, usare l'inizializzazione diretta:To correct the error, use direct initialization:

A a1{ 1 };
const A& a2{ 1 };

In Visual Studio 2015 il compilatore tratta erroneamente copy-list-initialization come l'oggetto copy-initialization normale, considerando solo la conversione dei costruttori per la risoluzione dell'overload.In Visual Studio 2015, the compiler erroneously treated copy-list-initialization in the same way as regular copy-initialization; it considered only converting constructors for overload resolution. Nell'esempio seguente Visual Studio 2015 sceglie MyInt(23) ma Visual Studio 2017 genera correttamente l'errore.In the following example, Visual Studio 2015 chooses MyInt(23) but Visual Studio 2017 correctly raises the error.

// From http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1228
struct MyStore {
       explicit MyStore(int initialCapacity);
};

struct MyInt {
       MyInt(int i);
};

struct Printer {
       void operator()(MyStore const& s);
       void operator()(MyInt const& i);
};

void f() {
       Printer p;
       p({ 23 }); // C3066: there are multiple ways that an object of this type can be called with these arguments
}

Questo esempio è simile a quello precedente, ma viene generato un errore diverso.This example is similar to the previous one but raises a different error. L'esito è positivo in Visual Studio 2015 e negativo in Visual Studio 2017 con C2668.It succeeds in Visual Studio 2015 and fails in Visual Studio 2017 with C2668.

struct A {
    explicit A(int) {}
};

struct B {
    B(int) {}
};

void f(const A&) {}
void f(const B&) {}

int main()
{
    f({ 1 }); // error C2668: 'f': ambiguous call to overloaded function
}

Typedef deprecatiDeprecated typedefs

Visual Studio 2017 ora genera l'avviso corretto per i typedef deprecati dichiarati in una classe o uno struct.Visual Studio 2017 now issues the correct warning for deprecated typedefs that are declared in a class or struct. L'esempio seguente viene compilato senza avvisi in Visual Studio 2015, ma genera l'avviso C4996 in Visual Studio 2017.The following example compiles without warnings in Visual Studio 2015 but produces C4996 in Visual Studio 2017.

struct A 
{
    // also for __declspec(deprecated) 
    [[deprecated]] typedef int inttype;
};

int main()
{
    A::inttype a = 0; // C4996 'A::inttype': was declared deprecated
}

constexprconstexpr

Visual Studio 2017 genera correttamente un errore quando l'operando sinistro di un'operazione con valutazione condizionale non è valido in un contesto constexpr.Visual Studio 2017 correctly raises an error when the left-hand operand of a conditionally evaluating operation is not valid in a constexpr context. Il codice seguente viene compilato in Visual Studio 2015, ma non in Visual Studio 2017 (C3615 la funzione constexpr 'f' non può restituire un'espressione costante):The following code compiles in Visual Studio 2015 but not in Visual Studio 2017 (C3615 constexpr function 'f' cannot result in a constant expression):

template<int N>
struct array 
{
       int size() const { return N; }
};

constexpr bool f(const array<1> &arr)
{
       return arr.size() == 10 || arr.size() == 11; // C3615    
}

Per correggere l'errore, dichiarare la funzione array:: size() come constexpr o rimuovere il qualificatore constexpr da f.To correct the error, either declare the array::size() function as constexpr or remove the constexpr qualifier from f.

Tipi di classe passati alle funzioni variadicClass types passed to variadic functions

In Visual Studio 2017 le classi o gli struct che vengono passati a una funzione variadic, ad esempio printf, devono essere facilmente copiabili.In Visual Studio 2017, classes or structs that are passed to a variadic function such as printf must be trivially copyable. Quando si passano tali oggetti il compilatore si limita a creare una copia bit per bit e non chiama il costruttore o distruttore.When passing such objects, the compiler simply makes a bitwise copy and does not call the constructor or destructor.

#include <atomic>
#include <memory>
#include <stdio.h>

int main()
{
    std::atomic<int> i(0);
    printf("%i\n", i); // error C4839: non-standard use of class 'std::atomic<int>'
                        // as an argument to a variadic function
                        // note: the constructor and destructor will not be called; 
                        // a bitwise copy of the class will be passed as the argument
                        // error C2280: 'std::atomic<int>::atomic(const std::atomic<int> &)':
                        // attempting to reference a deleted function

    struct S {
        S(int i) : i(i) {}
        S(const S& other) : i(other.i) {}
        operator int() { return i; }
    private:
        int i;
    } s(0);
    printf("%i\n", s); // warning C4840 : non-portable use of class 'main::S'
                      // as an argument to a variadic function
}

Per correggere l'errore, è possibile chiamare una funzione membro che restituisca un tipo facilmente copiabileTo correct the error, you can call a member function that returns a trivially copyable type,

    std::atomic<int> i(0);
    printf("%i\n", i.load());

o esegua un cast statico per convertire l'oggetto prima di passarlo:or else perform a static cast to convert the object before passing it:

    struct S {/* as before */} s(0);
    printf("%i\n", static_cast<int>(s))

Per le stringhe compilate e gestite usando CStringW, operator LPCWSTR() specificato deve essere usato per il cast di un oggetto CStringW al puntatore C previsto dalla stringa di formato.For strings built and managed using CStringW, the provided operator LPCWSTR() should be used to cast a CStringW object to the C pointer expected by the format string.

CStringW str1;
CStringW str2;
str1.Format(L"%s", static_cast<LPCWSTR>(str2));

Qualificatori CV nella costruzione di classicv-qualifiers in class construction

In Visual Studio 2015 il compilatore a volte ignora erroneamente il qualificatore CV quando genera un oggetto classe usando una chiamata al costruttore.In Visual Studio 2015, the compiler sometimes incorrectly ignores the cv-qualifier when generating a class object via a constructor call. Questo potenzialmente può causare un arresto anomalo o un comportamento imprevisto in fase di esecuzione.This can potentially cause a crash or unexpected runtime behavior. L'esempio seguente viene compilato in Visual Studio 2015, ma genera un errore del compilatore in Visual Studio 2017:The following example compiles in Visual Studio 2015 but raises a compiler error in Visual Studio 2017:

struct S 
{
    S(int);
    operator int();
};

int i = (const S)0; // error C2440

Per correggere l'errore, dichiarare l'operatore int() come const.To correct the error, declare operator int() as const.

Controllo dell'accesso per i nomi completi nei modelliAccess checking on qualified names in templates

Le versioni precedenti del compilatore non eseguivano il controllo dell'accesso per i nomi completi in alcuni contesti di modello.Previous versions of the compiler did not perform access checking on qualified names in some template contexts. Ciò può interferire con il comportamento previsto per SFINAE in cui la sostituzione deve avere esito negativo a causa della non accessibilità di un nome.This can interfere with expected SFINAE behavior where the substitution is expected to fail due to the inaccessibility of a name. Questo potrebbe avere causato un arresto anomalo o un comportamento imprevisto in fase di esecuzione perché il compilatore ha chiamato per errore l'overload dell'operatore non corretto.This could have potentially caused a crash or unexpected behavior at runtime due to the compiler incorrectly calling the wrong overload of the operator. In Visual Studio 2017 viene generato un errore del compilatore.In Visual Studio 2017, a compiler error is raised. L'errore specifico può variare, ma in genere è "C2672: non sono state trovate funzioni in overload corrispondenti".The specific error might vary but typically it is "C2672 no matching overloaded function found". Il codice seguente viene compilato in Visual Studio 2015 ma genera un errore in Visual Studio 2017:The following code compiles in Visual Studio 2015 but raises an error in Visual Studio 2017:

#include <type_traits>

template <class T> class S {
       typedef typename T type;
};

template <class T, std::enable_if<std::is_integral<typename S<T>::type>::value, T> * = 0>
bool f(T x);

int main()
{
       f(10); // C2672: No matching overloaded function found. 
}

Elenchi di argomenti di modello mancantiMissing template argument lists

In Visual Studio 2015 e versioni precedenti il compilatore non diagnosticava gli elenchi di argomenti di modello mancanti quando il modello era visualizzato in un elenco di parametri di modello, ad esempio come parte di un argomento di modello predefinito o un parametro di modello non di tipo.In Visual Studio 2015 and earlier, the compiler did not diagnose missing template argument lists when the template appeared in a template parameter list (for example as part of a default template argument or a non-type template parameter). Ciò può causare un comportamento imprevedibile, compresi arresti anomali del compilatore o il comportamento imprevisto in fase di esecuzione.This can result in unpredictable behavior, including compiler crashes or unexpected runtime behavior. Il codice seguente viene compilato in Visual Studio 2015 ma genera un errore in Visual Studio 2017.The following code compiles in Visual Studio 2015 but produces an error in Visual Studio 2017.

template <class T> class ListNode;
template <class T> using ListNodeMember = ListNode<T> T::*;
template <class T, ListNodeMember M> class ListHead; // C2955: 'ListNodeMember': use of alias 
                                                     // template requires template argument list

// correct:  template <class T, ListNodeMember<T> M> class ListHead;  

Espressione SFINAEExpression-SFINAE

Per supportare l'espressione SFINAE, il compilatore ora analizza argomenti decltype quando i modelli vengono dichiarati senza creare un'istanza.To support expression-SFINAE, the compiler now parses decltype arguments when the templates are declared rather than instantiated. Di conseguenza, se viene rilevata una specializzazione non dipendente nell'argomento decltype, non verrà rinviata all'ora di creazione di un'istanza ma verrà elaborata immediatamente e sarà possibile diagnosticare eventuali errori risultanti in quel momento.Consequently, if a non-dependent specialization is found in the decltype argument, it will not be deferred to instantiation-time and will be processed immediately and any resulting errors will be diagnosed at that time.

Nell'esempio seguente viene illustrato questo tipo di errore del compilatore che viene generato al momento della dichiarazione:The following example shows such a compiler error that is raised at the point of declaration:

#include <utility>
template <class T, class ReturnT, class... ArgsT> class IsCallable
{
public:
       struct BadType {};
       template <class U>
       static decltype(std::declval<T>()(std::declval<ArgsT>()...)) Test(int); //C2064. Should be declval<U>
       template <class U>
       static BadType Test(...);
       static constexpr bool value = std::is_convertible<decltype(Test<T>(0)), ReturnT>::value;
};

constexpr bool test1 = IsCallable<int(), int>::value;
static_assert(test1, "PASS1");
constexpr bool test2 = !IsCallable<int*, int>::value;
static_assert(test2, "PASS2");

Classi dichiarate in spazi dei nomi anonimiClasses declared in anonymous namespaces

In base allo standard C++, una classe dichiarata all'interno di uno spazio dei nomi anonimo include un collegamento interno e pertanto non può essere esportata.According to the C++ standard, a class declared inside an anonymous namespace has internal linkage, and therefore cannot be exported. In Visual Studio 2015 e versioni precedenti questa regola non viene applicata.In Visual Studio 2015 and earlier, this rule was not enforced. In Visual Studio 2017 la regola viene applicata parzialmente.In Visual Studio 2017 the rule is partially enforced. L'esempio seguente genera questo errore in Visual Studio 2017: "errore C2201: const anonymous namespace::S1::vftable: per l'esportazione e l'importazione è necessario utilizzare il collegamento esterno."The following example raises this error in Visual Studio 2017: "error C2201: const anonymous namespace::S1::vftable: must have external linkage in order to be exported/imported."

struct __declspec(dllexport) S1 { virtual void f() {} }; //C2201

Inizializzatori predefiniti per i membri della classe di valori (C++/CLI)Default initializers for value class members (C++/CLI)

In Visual Studio 2015 e versioni precedenti il compilatore consentiva, ma ignorava, un inizializzatore di membro predefinito per un membro di una classe di valori.In Visual Studio 2015 and earlier, the compiler permitted (but ignored) a default member initializer for a member of a value class. L'inizializzazione predefinita di una classe di valori inizializza sempre a zero i membri e un costruttore predefinito non è consentito.Default initialization of a value class always zero-initializes the members; a default constructor is not permitted. In Visual Studio 2017 gli inizializzatori di membri predefiniti generano un errore del compilatore, come illustra l'esempio seguente:In Visual Studio 2017, default member initializers raise a compiler error, as shown in this example:

value struct V
{
       int i = 0; // error C3446: 'V::i': a default member initializer  
                  // is not allowed for a member of a value class
};

Indicizzatori predefiniti (C++/CLI)Default Indexers (C++/CLI)

In Visual Studio 2015 e versioni precedenti il compilatore in alcuni casi identificava erroneamente una proprietà predefinita come indicizzatore predefinito.In Visual Studio 2015 and earlier, the compiler in some cases misidentified a default property as a default indexer. È stato possibile risolvere il problema usando l'identificatore "default" per accedere alla proprietà.It was possible to work around the issue by using the identifier "default" to access the property. Questa soluzione è diventata problematica dopo che il termine "default" è stato introdotto come parola chiave in C++11.The workaround itself became problematic after default was introduced as a keyword in C++11. Pertanto, in Visual Studio 2017 sono stati corretti i bug che richiedevano la soluzione e il compilatore genera ora un errore quando si usa "default" per accedere alla proprietà predefinita per una classe.Therefore, in Visual Studio 2017 the bugs that required the workaround were fixed, and the compiler now raises an error when "default" is used to access the default property for a class.

//class1.cs

using System.Reflection;
using System.Runtime.InteropServices;

namespace ClassLibrary1
{
    [DefaultMember("Value")]
    public class Class1
    {
        public int Value
        {
            // using attribute on the return type triggers the compiler bug
            [return: MarshalAs(UnmanagedType.I4)]
            get;
        }
    }
    [DefaultMember("Value")]
    public class Class2
    {
        public int Value
        {
            get;
        }
    }
}


// code.cpp
#using "class1.dll"

void f(ClassLibrary1::Class1 ^r1, ClassLibrary1::Class2 ^r2)
{
       r1->Value; // error
       r1->default;
       r2->Value;
       r2->default; // error
}

In Visual Studio 2017 è possibile accedere a entrambe le proprietà Value in base al nome:In Visual Studio 2017, you can access both Value properties by their name:

#using "class1.dll"

void f(ClassLibrary1::Class1 ^r1, ClassLibrary1::Class2 ^r2)
{
       r1->Value;
       r2->Value;
}

Correzioni di bug in Visual Studio 2017 versione 15.3 Bug fixes in Visual Studio 2017 version 15.3

Chiamate a modelli di membro eliminatiCalls to deleted member templates

Nelle versioni precedenti di Visual Studio, in alcuni casi il compilatore non riusciva a generare un errore in caso di chiamate non valide a un modello di membro eliminato che potevano causare arresti anomali in fase di runtime.In previous versions of Visual Studio, the compiler in some cases would fail to emit an error for ill-formed calls to a deleted member template which would’ve potentially caused crashes at runtime. Il codice seguente genera ora l'errore C2280, "'int S::f(void)': tentativo di fare riferimento a una funzione eliminata":The following code now produces C2280, "'int S::f(void)': attempting to reference a deleted function":

template<typename T> 
struct S { 
   template<typename U> static int f() = delete; 
}; 

void g() 
{ 
   decltype(S<int>::f<int>()) i; // this should fail 
}

Per correggere l'errore, dichiarare i come int.To fix the error, declare i as int.

Controlli sulle precondizioni per tratti di tipoPre-condition checks for type traits

Visual Studio 2017 versione 15.3 migliora i controlli sulle precondizioni per i tratti di tipo in modo da attenersi più rigorosamente agli standard.Visual Studio 2017 version 15.3 improves pre-condition checks for type-traits to more strictly follow the standard. Un controllo di questo tipo verifica ad esempio che il tratto di tipo sia assegnabile.One such check is for assignable. In Visual Studio 2017 versione 15.3 il codice seguente genera l'errore C2139:The following code produces C2139 in Visual Studio 2017 version 15.3:

struct S; 
enum E; 

static_assert(!__is_assignable(S, S), "fail"); // C2139 in 15.3
static_assert(__is_convertible_to(E, E), "fail"); // C2139 in 15.3

Nuovi controlli di avviso e di runtime del compilatore sul marshalling da nativo a gestitoNew compiler warning and runtime checks on native-to-managed marshaling

Le chiamate da funzioni gestite a funzioni native richiedono il marshalling.Calling from managed functions to native functions requires marshalling. CLR esegue il marshalling ma non comprende la semantica di C++.The CLR performs the marshaling but it doesn't understand C++ semantics. Se si passa un oggetto nativo per valore, CLR chiama il costruttore di copia dell'oggetto o usa BitBlt, da cui può derivare un comportamento non definito in fase di runtime.If you pass a native object by value, CLR will either call the object's copy-constructor or use BitBlt, which may cause undefined behavior at runtime.

Il compilatore genera ora un avviso se riesce a sapere in fase di runtime che tra il limite nativo e quello gestito viene passato per valore un oggetto con costruttore di copia eliminato.Now the compiler will emit a warning if it can know at compile time that a native object with deleted copy ctor is passed between native and managed boundary by value. Se il compilatore non viene a conoscenza di questo evento in fase di runtime, inserisce un controllo di runtime in modo che il programma chiami immediatamente std::terminate nel momento in cui si verifica un marshalling non valido.For those cases in which the compiler doesn't know at compile time, it will inject a runtime check so that the program will call std::terminate immediately when an ill-formed marshalling occurs. In Visual Studio 2017 versione 15.3 il codice seguente genera l'errore C4606 "'A': per il passaggio dell'argomento per valore tra limite nativo e gestito è necessario un costruttore di copia valido.In Visual Studio 2017 version 15.3, the following code produces C4606 " 'A': passing argument by value across native and managed boundary requires valid copy constructor. In caso contrario, il comportamento del runtime risulta non definito".Otherwise the runtime behavior is undefined".

class A 
{ 
public: 
   A() : p_(new int) {} 
   ~A() { delete p_; } 

   A(A const &) = delete; 
   A(A &&rhs) { 
   p_ = rhs.p_; 
} 

private: 
   int *p_; 
}; 

#pragma unmanaged 

void f(A a) 
{ 
} 

#pragma managed 

int main() 
{ 
    f(A()); // This call from managed to native requires marshalling. The CLR doesn't understand C++ and uses BitBlt, which will result in a double-free later. 
}

Per correggere l'errore, rimuovere la direttiva #pragma managed per contrassegnare il chiamante come nativo ed evitare il marshalling.To fix the error, remove the #pragma managed directive to mark the caller as native and avoid marshalling.

Avviso di API sperimentale per WinRTExperimental API warning for WinRT

Le API WinRT rilasciate a scopo di sperimentazione e feedback vengono contrassegnate con Windows.Foundation.Metadata.ExperimentalAttribute.WinRT APIs that are released for experimentation and feedback will be decorated with Windows.Foundation.Metadata.ExperimentalAttribute. In Visual Studio 2017 versione 15.3, il compilatore genera l'avviso C4698 quando rileva questo attributo.In Visual Studio 2017 version 15.3, the compiler will produce warning C4698 when it encounters the attribute. Alcune API presenti in versioni precedenti di Windows SDK sono già state contrassegnate con questo attributo e le chiamate a queste API attiveranno quindi l'avviso del compilatore.A few APIs in previous versions of the Windows SDK have already been decorated with the attribute, and calls to these APIs will start triggering this compiler warning. Nelle nuove versioni di Windows SDK l'attributo verrà rimosso da tutti i tipi distribuiti, ma se si usa un SDK precedente sarà necessario eliminare questi avvisi per tutte le chiamate effettuate ai tipi distribuiti.Newer Windows SDKs will have the attribute removed from all shipped types, but if you are using an older SDK, you'll need to suppress these warnings for all calls to shipped types. Il codice seguente genera l'avviso C4698: "'Windows::Storage::IApplicationDataStatics2::GetForUserAsync' viene usato solo a scopo di valutazione e potrebbe essere modificato o rimosso in aggiornamenti futuri":The following code produces warning C4698: "'Windows::Storage::IApplicationDataStatics2::GetForUserAsync' is for evaluation purposes only and is subject to change or removal in future updates":

Windows::Storage::IApplicationDataStatics2::GetForUserAsync() //C4698

Per disabilitare l'avviso, aggiungere #pragma:To disable the warning, add a #pragma:

#pragma warning(push) 
#pragma warning(disable:4698) 

Windows::Storage::IApplicationDataStatics2::GetForUserAsync() 

#pragma warning(pop)

Definizione out-of-line di una funzione membro di modelloOut-of-line definition of a template member function

Visual Studio 2017 versione 15.3 genera un errore quando rileva una definizione out-of-line di una funzione membro di modello non dichiarata nella classe.Visual Studio 2017 version 15.3 produces an error when it encounters an out-of-line definition of a template member function that was not declared in the class. Il codice seguente genera ora l'errore C2039: 'f': non è un membro di 'S':The following code now produces error C2039: 'f': is not a member of 'S':

struct S {}; 

template <typename T> 
void S::f(T t) {} //C2039: 'f': is not a member of 'S'

Per correggere l'errore, aggiungere una dichiarazione alla classe:To fix the error, add a declaration to the class:

struct S { 
    template <typename T> 
    void f(T t); 
}; 
template <typename T> 
void S::f(T t) {}

Tentativo di accettare l'indirizzo del puntatore "this"Attempting to take the address of "this" pointer

In C++, 'this' è un prvalue di tipo puntatore a X. Non è possibile accettare l'indirizzo di 'this' o associarlo a un riferimento lvalue.In C++ 'this' is an prvalue of type pointer to X. You cannot take the address of 'this' or bind it to an lvalue reference. Nelle versioni precedenti di Visual Studio, il compilatore consentiva di ignorare questa restrizione eseguendo un cast.In previous versions of Visual Studio, the compiler would allow you to circumvent this restriction by performing a cast. In Visual Studio 2017 versione 15.3, il compilatore genera l'errore C2664.In Visual Studio 2017 version 15.3, the compiler produces error C2664.

Conversione a una classe di base inaccessibileConversion to an inaccessible base class

Visual Studio 2017 versione 15.3 genera un errore quando si prova a convertire un tipo in una classe di base inaccessibile.Visual Studio 2017 version 15.3 produces an error when you attempt to convert a type to a base class which is inaccessible. L'errore ora generato dal compilatore è "errore C2243: 'type cast': conversione da 'D *' a 'B *' esistente ma inaccessibile".The compiler now raises "error C2243: 'type cast': conversion from 'D *' to 'B *' exists, but is inaccessible". Il codice seguente non è valido e può causare un arresto anomalo in fase di runtime.The following code is ill-formed and can potentially cause a crash at runtime. Il compilatore genera ora un errore C2243 quando rileva un codice simile al seguente:The compiler now produces C2243 when it encounters code like this:

#include <memory> 

class B { }; 
class D : B { }; // C2243. should be public B { }; 

void f() 
{ 
   std::unique_ptr<B>(new D()); 
}

Gli argomenti predefiniti non sono consentiti nelle definizioni out-of-line di funzioni membroDefault arguments are not allowed on out of line definitions of member functions

Gli argomenti predefiniti non sono consentiti nelle definizioni out-of-line di funzioni membro presenti in classi modello. Il compilatore genererà un avviso per /permissive e un errore grave per /permissive-.Default arguments are not allowed on out-of-line definitions of member functions in template classes The compiler will issue a warning under /permissive, and a hard error under /permissive-.

Nelle versioni precedenti di Visual Studio, il codice non valido seguente poteva causare potenzialmente un arresto anomalo in fase di runtime.In previous versions of Visual Studio, the following ill-formed code could potentially cause a runtime crash. Visual Studio 2017 versione 15.3 genera l'avviso C5034: 'A::f': una definizione out-of-line di un membro di una classe non può contenere argomenti predefiniti:Visual Studio 2017 version 15.3 produces warning C5034: 'A::f': an out-of-line definition of a member of a class template cannot have default arguments:


template <typename T> 
struct A { 
    T f(T t, bool b = false); 
}; 

template <typename T> 
T A<T>::f(T t, bool b = false) // C5034
{ 
... 
}

Per correggere l'errore, rimuovere l'argomento predefinito "= false".To fix the error, remove the "= false" default argument.

Uso di offsetof con indicatore di membro compostoUse of offsetof with compound member designator

In Visual Studio 2017 versione 15.3, l'uso di offsetof(T, m) in cui m è un "indicatore di membro composto" risulterà in un avviso se si esegue la compilazione con l'opzione /Wall.In Visual Studio 2017 version 15.3, using offsetof(T, m) where m is a "compound member designator" will result in a warning when you compile with the /Wall option. Il codice seguente non è valido e può causare un arresto anomalo in fase di runtime.The following code is ill-formed and could potentially cause a crash at runtime. Visual Studio 2017 versione 15.3 produce l'avviso C4841: "è stata usata un'estensione non standard: indicatore di membro composto usato in offsetof":Visual Studio 2017 version 15.3 produces "warning C4841: non-standard extension used: compound member designator in offseto":


struct A { 
int arr[10]; 
}; 

// warning C4841: non-standard extension used: compound member designator in offsetof 
constexpr auto off = offsetof(A, arr[2]);

Per correggere il codice, disabilitare l'avviso con un pragma o modificare il codice in modo da non usare offsetof:To fix the code, either disable the warning with a pragma or change the code to not use offsetof:

#pragma warning(push) 
#pragma warning(disable: 4841) 
constexpr auto off = offsetof(A, arr[2]); 
#pragma warning(pop) 

Uso di offsetof con una funzione membro o un membro dati staticiUsing offsetof with static data member or member function

In Visual Studio 2017 versione 15.3, l'uso di offsetof (T, m) in cui m fa riferimento a un membro dati statici o a una funzione membro determinerà un errore.In Visual Studio 2017 version 15.3, using offsetof(T, m) where m refers to a static data member or a member function will result in an error. Il codice seguente produce l'errore C4597: "undefined behavior: offsetof applied to member function 'foo'" (comportamento indefinito: offsetof applicato alla funzione membro 'foo') e l'errore C4597: "undefined behavior: offsetof applied to static data member 'bar'" (comportamento indefinito: offsetof applicato al membro dati statici 'bar'):The following code produces "error C4597: undefined behavior: offsetof applied to member function 'foo'" and "error C4597: undefined behavior: offsetof applied to static data member 'bar'":


#include <cstddef> 

struct A { 
int foo() { return 10; } 
static constexpr int bar = 0; 
}; 

constexpr auto off = offsetof(A, foo); 
Constexpr auto off2 = offsetof(A, bar);

Questo codice non è valido e può causare un arresto anomalo in fase di runtime.This code is ill-formed and could potentially cause a crash at runtime. Per correggere l'errore, modificare il codice in modo da non richiamare più un comportamento indefinito.To fix the error, change the code to no longer invoke undefined behavior. Si tratta di codice non portabile non consentito dallo standard C++.This is non-portable code that is disallowed by the C++ standard.

Nuovo avviso per attributi declspec New warning on declspec attributes

In Visual Studio 2017 versione 15.3, il compilatore non ignora più gli attributi se prima della specifica di collegamento "C" esterna viene applicato l'attributo __declspec(...).In Visual Studio 2017 version 15.3, the compiler no longer ignores attributes if __declspec(…) is applied before extern "C" linkage specification. In precedenza, il compilatore avrebbe ignorato l'attributo, con possibili implicazioni in fase di runtime.Previously, the compiler would ignore the attritbute, which could have runtime implications. Se è stata impostata l'opzione /Wall /WX, il codice seguente produce l'avviso C4768: "__declspec attributes before linkage specification are ignored" (gli attributi __declspec prima della specifica di collegamento sono stati ignorati):When the /Wall /WX option is set, the following code produces "warning C4768: __declspec attributes before linkage specification are ignored":


__declspec(noinline) extern "C" HRESULT __stdcall //C4768

Per risolvere il problema, inserire prima la specifica "C" esterna:To fix the warning, put extern "C" first:

extern "C" __declspec(noinline) HRESULT __stdcall

Questo avviso è disattivato per impostazione predefinita (attivato per impostazione predefinita nella versione 15.5) e influisce solo su codice compilato con /Wall /WX.This warning is off-by-default (on by default in 15.5) and only impacts code compiled with /Wall /WX.

decltype e chiamate a distruttori eliminatidecltype and calls to deleted destructors

Nelle versioni precedenti di Visual Studio, il compilatore non era in grado di rilevare se si verificava una chiamata a un distruttore eliminato nel contesto dell'espressione associata a 'decltype'.In previous versions of Visual Studio, the compiler did not detect when a call to a deleted destructor occurred in the context of the expression associated with 'decltype'. In Visual Studio 2017 versione 15.3, il codice seguente genera "errore C2280: 'A::~A(void)': tentativo di fare riferimento a una funzione eliminata":In Visual Studio 2017 version 15.3, the following code produces "error C2280: 'A::~A(void)': attempting to reference a deleted function":

template<typename T> 
struct A 
{ 
   ~A() = delete; 
}; 

template<typename T> 
auto f() -> A<T>; 

template<typename T> 
auto g(T) -> decltype((f<T>())); 

void h() 
{ 
   g(42); 
}

Variabili const non inizializzateUninitialized const variables

Visual Studio 2017 RTW conteneva una regressione in cui il compilatore C++ non generava un messaggio di diagnostica se non veniva inizializzata una variabile 'const'.Visual Studio 2017 RTW release had a regression in which the C++ compiler would not issue a diagnostic if a 'const' variable was not initialized. Questa regressione è stata risolta in Visual Studio 2017 versione 15.3.This regression has been fixed in Visual Studio 2017 version 15.3. Il codice seguente produce ora "avviso C4132: 'Value': oggetto const da inizializzare":The following code now produces "warning C4132: 'Value': const object should be initialized":

const int Value; //C4132

Per correggere l'errore, assegnare un valore a Value.To fix the error, assign a value to Value.

Dichiarazioni vuoteEmpty declarations

Visual Studio 2017 versione 15.3 genera ora un avviso in presenza di dichiarazioni vuote per tutti i tipi, non solo per i tipi predefiniti.Visual Studio 2017 version 15.3 now warns on empty declarations for all types, not just built-in types. Il codice seguente genera ora un avviso C4091 di livello 2 per tutte le quattro dichiarazioni:The following code now produces a level 2 C4091 warning for all four declarations:

struct A {};
template <typename> struct B {};
enum C { c1, c2, c3 };

int;    // warning C4091 : '' : ignored on left of 'int' when no variable is declared
A;      // warning C4091 : '' : ignored on left of 'main::A' when no variable is declared
B<int>; // warning C4091 : '' : ignored on left of 'B<int>' when no variable is declared
C;      // warning C4091 : '' : ignored on left of 'C' when no variable is declared

Per rimuovere gli avvisi, è sufficiente impostare le dichiarazioni vuote come commento o rimuoverle.To remove the warnings, simply comment-out or remove the empty declarations. Se l'oggetto senza nome deve avere un effetto collaterale (ad esempio, RAII), è opportuno assegnare un nome all'oggetto.In cases where the un-named object is intended to have a side effect (such as RAII) it should be given a name.

L'avviso viene escluso in /Wv:18 ed è attivo per impostazione predefinita nel livello di avviso W2.The warning is excluded under /Wv:18 and is on by default under warning level W2.

std::is_convertible per i tipi matricestd::is_convertible for array types

Le versioni precedenti del compilatore restituiscono risultati non corretti per std::is_convertible per i tipi matrice.Previous versions of the compiler gave incorrect results for std::is_convertible for array types. Per questo motivo, gli autori delle librerie dovevano gestire come caso speciale il compilatore Visual C++ quando veniva usato il tratto di tipo std::is_convertible<…>.This required library writers to special-case the Visual C++ compiler when using the std::is_convertible<…> type trait. Nell'esempio seguente le asserzioni statiche hanno esito positivo nelle versioni precedenti di Visual Studio, ma negativo in Visual Studio 2017 versione 15.3:In the following example, the static asserts pass in earlier versions of Visual Studio but fail in Visual Studio 2017 version 15.3:

#include <type_traits>

using Array = char[1];

static_assert(std::is_convertible<Array, Array>::value);
static_assert(std::is_convertible<const Array, const Array>::value, "");
static_assert(std::is_convertible<Array&, Array>::value, "");
static_assert(std::is_convertible<Array, Array&>::value, "");

std::is_convertible<From, To> viene calcolato controllando se una definizione di funzione immaginaria è ben formata:std::is_convertible<From, To> is calculated by checking to see if an imaginary function definition is well formed:

   To test() { return std::declval<From>(); }

Distruttori privati e std::is_constructiblePrivate destructors and std::is_constructible

Le versioni precedenti del compilatore ignorano il fatto che un distruttore sia privato al momento di decidere il risultato di std::is_constructible.Previous versions of the compiler ignored whether a destructor was private when deciding the result of std::is_constructible. Questa condizione viene ora presa in considerazione.It now considers them. Nell'esempio seguente le asserzioni statiche hanno esito positivo nelle versioni precedenti di Visual Studio, ma negativo in Visual Studio 2017 versione 15.3:In the following example, the static asserts pass in earlier versions of Visual Studio but fail in Visual Studio 2017 version 15.3:

#include <type_traits>

class PrivateDtor {
   PrivateDtor(int) { }
private:
   ~PrivateDtor() { }
};

// This assertion used to succeed. It now correctly fails.
static_assert(std::is_constructible<PrivateDtor, int>::value);

A causa dei distruttori privati un tipo può essere non costruibile.Private destructors cause a type to be non-constructible. std::is_constructible<T, Args…> viene calcolato come se fosse scritta la dichiarazione seguente:std::is_constructible<T, Args…> is calculated as if the following declaration were written:

   T obj(std::declval<Args>()…)

Questa chiamata implica una chiamata al distruttore.This call implies a destructor call.

C2668: risoluzione ambigua dell'overloadC2668: Ambiguous overload resolution

Le versioni precedenti del compilatore talvolta non riescono a rilevare ambiguità quando vengono trovati più candidati sia tramite dichiarazioni che ricerche dipendenti dall'argomento.Previous versions of the compiler sometimes failed to detect ambiguity when it found multiple candidates via both using declarations and argument dependent lookup. Ciò può portare alla scelta di un overload non corretto e a un comportamento di runtime imprevisto.This can lead to wrong overload being chosen and unexpected runtime behavior. Nell'esempio seguente Visual Studio 2017 versione 15.3 genera correttamente C2668 'f': chiamata ambigua a funzione in overload:In the following example, Visual Studio 2017 version 15.3 correctly raises C2668 'f': ambiguous call to overloaded function:

namespace N {
   template<class T>
   void f(T&, T&);

   template<class T>
   void f();
}

template<class T>
void f(T&, T&);

struct S {};
void f()
{
   using N::f; 

   S s1, s2;
   f(s1, s2); // C2668
}

Per correggere il codice, rimuovere l'istruzione using N::f se l'intenzione era di chiamare :: f().To fix the code, remove the using N::f statement if you intended to call ::f().

C2660: dichiarazioni di funzione locali e ricerca dipendente dall'argomentoC2660: local function declarations and argument dependent lookup

Le dichiarazioni di funzione locali nascondono la dichiarazione di funzione nell'ambito che la contiene e disabilitano la ricerca dipendente dall'argomento.Local function declarations hide the function declaration in the enclosing scope and disable argument dependent lookup. Tuttavia, le versioni precedenti del compilatore Visual C++ eseguono la ricerca dipendente dall'argomento in questo caso, causando potenzialmente la scelta dell'overload non corretto e un comportamento di runtime imprevisto.However, previous versions of the Visual C++ compiler performed argument dependent lookup in this case, potentially leading to the wrong overload being chosen and unexpected runtime behavior. In genere, l'errore è dovuto a una firma non corretta della dichiarazione di funzione locale.Typically, the error is due to an incorrect signature of the local function declaration. Nell'esempio seguente Visual Studio 2017 versione 15.3 genera correttamente C2660 'f': la funzione non accetta 2 argomenti:In the following example, Visual Studio 2017 version 15.3 correctly raises C2660 'f': function does not take 2 arguments:

struct S {}; 
void f(S, int);

void g()
{
   void f(S); // C2660 'f': function does not take 2 arguments:
   // or void f(S, int);
   S s;
   f(s, 0);
}

Per risolvere il problema, modificare la firma f(S) o rimuoverla.To fix the problem, either change the f(S) signature or remove it.

C5038: ordine di inizializzazione negli elenchi di inizializzatoriC5038: order of initialization in initializer lists

I membri di classe vengono inizializzati nell'ordine in cui sono dichiarati e non l'ordine in cui compaiono negli elenchi di inizializzatori.Class members are initialized in the order they are declared, not the order they appear in initializer lists. Le versioni precedenti del compilatore non avvisano quando l'ordine dell'elenco di inizializzatori è diverso dall'ordine di dichiarazione.Previous versions of the compiler did not warn when the order of the initializer list differed from the order of declaration. Ciò può causare un comportamento di runtime indefinito se l'inizializzazione di un membro dipende dal fatto che un altro membro nell'elenco sia già inizializzato.This could lead to undefined runtime behavior if the intialization of one member depended on another member in the list already being initialized. Nell'esempio seguente Visual Studio 2017 versione 15.3 (con /Wall) genera l'avviso C5038: il membro dati 'A::y' verrà inizializzato dopo il membro dati 'A::x':In the following example, Visual Studio 2017 version 15.3 (with /Wall) raises warning C5038: data member 'A::y' will be initialized after data member 'A::x':

struct A
{
    A(int a) : y(a), x(y) {} // Initialized in reverse, y reused
    int x;
    int y;
};

Per risolvere il problema disporre l'elenco di inizializzatori nello stesso ordine delle dichiarazioni.To fix the problem arrange the intializer list to have the same order as the declarations. Viene generato un avviso analogo quando uno o entrambi gli inizializzatori fanno riferimento a membri della classe di base.A similar warning is raised when one or both initializers refer to base class members.

Si noti che l'avviso è disattivato per impostazione predefinita e influisce solo sul codice compilato con /Wall.Note that the warning is off-by-default and only affects code compiled with /Wall.

Correzioni di bug e altre modifiche di comportamento in Visual Studio 2017 versione 15.5 Bug fixes and other behavior changes in Visual Studio 2017 version 15.5

Modifica di ordinamento parzialePartial Ordering Change

Il compilatore ora rifiuta correttamente il codice seguente e visualizza il messaggio di errore corretto:The compiler now correctly rejects the following code and gives the correct error message:


template<typename... T>
int f(T* ...)
{
    return 1;
}

template<typename T>
int f(const T&)
{
    return 2;
}

int main()
{
    int i = 0;
    f(&i);    // C2668
}
t161.cpp
t161.cpp(16): error C2668: 'f': ambiguous call to overloaded function
t161.cpp(8): note: could be 'int f<int*>(const T &)'
        with
        [
            T=int*
        ]
t161.cpp(2): note: or       'int f<int>(int*)'
t161.cpp(16): note: while trying to match the argument list '(int*)'

Il problema nell'esempio precedente è la presenza di due differenze nei tipi (const rispetto a non-const e pack rispetto a non-pack).The problem in the example above is that there are two differences in the types (const vs. non-const and pack vs. non-pack). Per eliminare l'errore del compilatore, rimuovere una delle differenze.To eliminate the compiler error, remove one of the differences. In questo modo il compilatore può ordinare senza ambiguità le funzioni.This enables the compiler to unambiguously order the functions.

template<typename... T>
int f(T* ...)
{
    return 1;
}

template<typename T>
int f(T&)
{
    return 2;
}

int main()
{
    int i = 0;
    f(&i);
}

Gestori di eccezioniException handlers

I gestori del riferimento al tipo di matrice o di funzione non sono mai una corrispondenza per gli oggetti eccezione.Handlers of reference to array or function type are never a match for any exception object. Il compilatore ora rispetta correttamente questa regola e genera un avviso di livello 4.The compiler now correctly honors this rule and raises a level 4 warning. Non stabilisce neppure più una corrispondenza tra un gestore di char* o wchar_t* e un valore letterale stringa quando viene usato /Zc:strictStrings.It also no longer matches a handler of char* or wchar_t* to a string literal when /Zc:strictStrings is used.

int main()
{
    try {
        throw "";
    }
    catch (int (&)[1]) {} // C4843 (This should always be dead code.)
    catch (void (&)()) {} // C4843 (This should always be dead code.)
    catch (char*) {} // This should not be a match under /Zc:strictStrings
}
warning C4843: 'int (&)[1]': An exception handler of reference to array or function type is unreachable, use 'int*' instead
warning C4843: 'void (__cdecl &)(void)': An exception handler of reference to array or function type is unreachable, use 'void (__cdecl*)(void)' instead

Il codice seguente consente di evitare l'errore:The following code avoids the error:

catch (int (*)[1]) {}

Lo spazio dei nomi std::tr1 è deprecatostd::tr1 namespace is deprecated

Lo spazio dei nomi std::tr1 non standard è ora contrassegnato come deprecato in entrambe le modalità C++14 e C++17.The non-Standard std::tr1 namespace is now marked as deprecated in both C++14 and C++17 modes. In Visual Studio 2017 versione 15.5 il codice seguente genera l'errore C4996:In Visual Studio 2017 version 15.5, the following code raises C4996:

#include <functional>
#include <iostream>
using namespace std;

int main() {
    std::tr1::function<int (int, int)> f = std::plus<int>(); //C4996
    cout << f(3, 5) << std::endl;
    f = std::multiplies<int>();
    cout << f(3, 5) << std::endl;
}
warning C4996: 'std::tr1': warning STL4002: The non-Standard std::tr1 namespace and TR1-only machinery are deprecated and will be REMOVED. You can define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING to acknowledge that you have received this warning.

Per correggere l'errore, rimuovere il riferimento allo spazio dei nomi tr1:To fix the error, remove the reference to the tr1 namespace:

#include <functional>
#include <iostream>
using namespace std;

int main() {
    std::function<int (int, int)> f = std::plus<int>();
    cout << f(3, 5) << std::endl;
    f = std::multiplies<int>();
    cout << f(3, 5) << std::endl;
}

Le funzionalità della libreria standard in Annex D vengono contrassegnate come deprecateStandard Library features in Annex D are marked as deprecated.

Quando l'opzione del compilatore in modalità /std:c++17 è impostata, quasi tutte le funzionalità della libreria standard in Annex D vengono contrassegnate come deprecate.When the /std:c++17 mode compiler switch is set, almost all Standard Library features in Annex D are marked as deprecated.

In Visual Studio 2017 versione 15.5 il codice seguente genera l'errore C4996:In Visual Studio 2017 version 15.5, the following code raises C4996:

#include <iterator>

class MyIter : public std::iterator<std::random_access_iterator_tag, int> {
public:
    // ... other members ...
};

#include <type_traits>

static_assert(std::is_same<MyIter::pointer, int*>::value, "BOOM");
warning C4996: 'std::iterator<std::random_access_iterator_tag,int,ptrdiff_t,_Ty*,_Ty &>::pointer': warning STL4015: The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. (The <iterator> header is NOT deprecated.) The C++ Standard has never required user-defined iterators to derive from std::iterator. To fix this warning, stop deriving from std::iterator and start providing publicly accessible typedefs named iterator_category, value_type, difference_type, pointer, and reference. Note that value_type is required to be non-const, even for constant iterators. You can define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.

Per correggere l'errore, seguire le istruzioni nel testo dell'avviso, come illustrato nel codice seguente:To fix the error, follow the instructions in the warning text, as demonstrated in the following code:

#include <iterator>

class MyIter {
public:
    typedef std::random_access_iterator_tag iterator_category;
    typedef int value_type;
    typedef ptrdiff_t difference_type;
    typedef int* pointer;
    typedef int& reference;

    // ... other members ...
};

#include <type_traits>

static_assert(std::is_same<MyIter::pointer, int*>::value, "BOOM");

Variabili locali senza riferimentiUnreferenced local variables

In Visual Studio 15.5 l'avviso C4189 viene generato in diversi casi, come illustrato nel codice seguente:In Visual Studio 15.5, warning C4189 is emitted in more cases, as shown in the following code:

void f() {
    char s[2] = {0}; // C4189. Either use the variable or remove it.
}
warning C4189: 's': local variable is initialized but not referenced

Per correggere l'errore, rimuovere la variabile non usata.To fix the error, remove the unused variable.

Commenti a riga singolaSingle line comments

In Visual Studio 2017 versione 15.5 gli avvisi C4001 e C4179 non vengono più generati dal compilatore C.In Visual Studio 2017 version 15.5, warnings C4001 and C4179 are no longer emitted by the C compiler. In precedenza venivano generati solo nell'opzione del compilatore /Za.Previously, they were only emitted under the /Za compiler switch. Gli avvisi non sono più necessari perché i commenti a riga singola fanno parte dello standard C da C99.The warnings are no longer needed because single line comments have been part of the C standard since C99.

/* C only */
#pragma warning(disable:4001) //C4619
#pragma warning(disable:4179)
// single line comment
//* single line comment */
warning C4619: #pragma warning: there is no warning number '4001'   

Se non è necessario che il codice sia compatibile con le versioni precedenti, è possibile evitare l'avviso rimuovendo l'eliminazione di C4001/C4179.If the code does not need to be backwards compatible, you can avoid the warning by removing the C4001/C4179 suppression. Se è necessario che il codice sia compatibile con le versioni precedenti, eliminare solo C4619.If the code does need to be backward compatible, then suppress C4619 only.

/* C only */

#pragma warning(disable:4619)
#pragma warning(disable:4001)
#pragma warning(disable:4179)

// single line comment
/* single line comment */

Attributi __declspec con collegamento extern "C"__declspec attributes with extern "C" linkage

Nelle versioni precedenti di Visual Studio il compilatore ignora gli attributi __declspec(…) quando __declspec(…) viene applicato prima della specifica del collegamento extern "C".In earlier versions of Visual Studio, the compiler ignored __declspec(…) attributes when __declspec(…) was applied before the extern "C" linkage specification. Questo comportamento causa la generazione di codice non desiderato dall'utente, con possibili implicazioni per il runtime.This behavior caused code to be generated that user didn't intend, with possible runtime implications. L'avviso è stato aggiunto in Visual Studio versione 15.3, ma è disattivato per impostazione predefinita.The warning was added in Visual Studio version 15.3, but was off by default. In Visual Studio 2017 versione 15.5 l'avviso è abilitato per impostazione predefinita.In Visual Studio 2017 version 15.5, the warning is enabled by default.

__declspec(noinline) extern "C" HRESULT __stdcall //C4768
warning C4768: __declspec attributes before linkage specification are ignored

Per correggere l'errore, inserire la specifica del collegamento prima dell'attributo __declspec:To fix the error, place the linkage specification before the __declspec attribute:

extern "C" __declspec(noinline) HRESULT __stdcall

Questo nuovo avviso C4768 verrà visualizzato in alcune intestazioni di Windows SDK fornite con Visual Studio 2017 15.3 o versione precedente (ad esempio, la versione 10.0.15063.0, nota anche come RS2 SDK).This new warning C4768 will be given on some Windows SDK headers that were shipped with Visual Studio 2017 15.3 or older (for example: version 10.0.15063.0, also known as RS2 SDK). Le versioni successive di Windows SDK (in particolare, ShlObj.h e ShlObj_core.h) sono state tuttavia corrette in modo che non generino questo avviso.However, later versions of Windows SDK headers (specifically, ShlObj.h and ShlObj_core.h) have been fixed so that they do not produce this warning. Quando viene visualizzato questo avviso proveniente dalle azioni di Windows SDK, è possibile eseguire queste azioni:When you see this warning coming from Windows SDK headers, you can take these actions: 1) Passare alla versione più recente di Windows SDK fornita con Visual Studio 2017 15.5.Switch to the latest Windows SDK that came with Visual Studio 2017 15.5 release. 2) Disattivare l'avviso prima e dopo l'elemento #include dell'istruzione dell'intestazione di Windows SDK:Turn off the warning around the #include of the Windows SDK header statement:

#pragma warning (push) 
#pragma warning(disable:4768)
#include <shlobj.h>
#pragma warning (pop) 

Collegamento Extern constexprExtern constexpr linkage

Nelle versioni precedenti di Visual Studio il compilatore assegna sempre un collegamento interno della variabile constexpr anche quando la variabile è contrassegnata come extern.In earlier versions of Visual Studio, the compiler always gave a constexpr variable internal linkage even when the variable was marked extern. In Visual Studio 2017 versione 15.5 una nuova opzione del compilatore (/Zc:externConstexpr) abilita il comportamento corretto conforme agli standard.In Visual Studio 2017 version 15.5, a new compiler switch (/Zc:externConstexpr) enables correct standards-conforming behavior. Questo diventerà infine il comportamento predefinito.Eventually this will become the default.

extern constexpr int x = 10; 
error LNK2005: "int const x" already defined

Se un file di intestazione contiene una variabile dichiarata extern constexpr, è necessario contrassegnarla come __declspec(selectany) per combinarne correttamente le dichiarazioni duplicate:If a header file contains a variable declared extern constexpr, it needs to be marked __declspec(selectany) in order to correctly have its duplicate declarations combined:

extern constexpr __declspec(selectany) int x = 10;

typeid non può essere usato nel tipo di classe incompletotypeid can't be used on incomplete class type.

Nelle versioni precedenti di Visual Studio il compilatore consente erroneamente il codice seguente, che restituisce informazioni sul tipo potenzialmente non corrette.In earlier versions of Visual Studio, the compiler incorrectly allowed the following code, resulting in potentially incorrect type information. In Visual Studio 2017 versione 15.5 il compilatore genera correttamente un errore:In Visual Studio 2017 version 15.5, the compiler correctly raises an error:

#include <typeinfo>

struct S;

void f() { typeid(S); } //C2027 in 15.5
error C2027: use of undefined type 'S'

Tipo di destinazione std::is_convertiblestd::is_convertible target type

std::is_convertible richiede che il tipo di destinazione sia un tipo restituito valido.std::is_convertible requires the target type to be a valid return type. Nelle versioni precedenti di Visual Studio il compilatore consente erroneamente i tipi astratti, il che può causare una risoluzione dell'overload non corretta e un comportamento di runtime indesiderato.In earlier versions of Visual Studio, the compiler incorrectly allowed abstract types, which might lead to incorrect overload resolution and unintended runtime behavior. Il codice seguente ora genera correttamente l'errore C2338:The following code now correctly raises C2338:

#include <type_traits>

struct B { virtual ~B() = 0; };
struct D : public B { virtual ~D(); };

static_assert(std::is_convertible<D, B>::value, "fail"); // C2338 in 15.5

Per evitare l'errore, quando si usa is_convertible, è consigliabile confrontare i tipi di puntatore perché un confronto dei tipi non puntatore potrebbe non riuscire se un tipo è astratto:To avoid the error, when using is_convertible you should compare pointer types because a non-pointer-type comparison might fail if one type is abstract:

#include <type_traits>

struct B { virtual ~B() = 0; };
struct D : public B { virtual ~D(); };

static_assert(std::is_convertible<D *, B *>::value, "fail");

Rimozione della specifica di eccezione dinamica e noexcept Dynamic exception specification removal and noexcept

In C++17 throw() è un alias per noexcept, throw(<type list>) e throw(…) vengono rimossi e alcuni tipi possono includere noexcept.In C++17, throw() is an alias for noexcept, throw(<type list>) and throw(…) are removed, and certain types may include noexcept. Ciò può causare problemi di compatibilità di origine con il codice conforme a C++14 o versione precedente.This can cause source compatibility issues with code that conforms to C++14 or earlier. L'opzione /Zc:noexceptTypes- può essere usata per ripristinare la versione C++14 di noexcept durante l'uso della modalità C++ 17 in generale.The /Zc:noexceptTypes- switch can be used to revert to the C++14 version of noexcept while using C++17 mode in general. In questo modo è possibile aggiornare il codice sorgente per garantire la conformità a C++17 senza dover riscrivere contemporaneamente tutto il codice throw().This enables you to update your source code to conform to C++17 without having to rewrite all your throw() code at the same time.

Il compilatore ora diagnostica anche altre specifiche di eccezione non corrispondenti nelle dichiarazioni in modalità C++17 o con /permissive- con il nuovo avviso C5043.The compiler also now diagnoses more mismatched exception specifications in declarations in C++17 mode or with /permissive- with the new warning C5043.

Il codice seguente genera C5043 e C5040 in Visual Studio 2017 versione 15.5 quando viene applicata l'opzione /std:c++17:The following code generates C5043 and C5040 in Visual Studio 2017 version 15.5 when the /std:c++17 switch is applied:

void f() throw(); // equivalent to void f() noexcept;
void f() {} // warning C5043
void g() throw(); // warning C5040

struct A {
    virtual void f() throw();
};

struct B : A {
    virtual void f() { } // error C2694
};

Per rimuovere gli errori quando si usa ancora /std:c++17, aggiungere l'opzione /Zc:noexceptTypes- alla riga di comando o aggiornare il codice per usare noexcept, come illustrato nell'esempio seguente:To remove the errors while still using /std:c++17, either add the /Zc:noexceptTypes- switch to the command line, or else update your code to use noexcept, as shown in the following example:

void f() noexcept;
void f() noexcept { }
void g() noexcept(false);

struct A {
    virtual void f() noexcept;
};

struct B : A {
    virtual void f() noexcept { }
};

Variabili inlineInline variables

I membri dati static constexpr ora sono implicitamente inline, quindi la loro dichiarazione in una classe ora è la loro definizione.Static constexpr data members are now implicitly inline, which means that their declaration within a class is now their definition. L'uso di una definizione out-of-line per un membro dati static constexpr è ridondante e attualmente deprecato.Using an out-of-line definition for a static constexpr data member is redundant, and now deprecated. In Visual Studio 2017 versione 15.5 quando viene applicata l'opzione /std:c++17, il codice seguente ora genera l'avviso C5041 'size': la definizione out-of-line per il membro dati statico constexpr non è necessaria ed è deprecata in C++17:In Visual Studio 2017 version 15.5 when the /std:c++17 switch is applied, the following code now produces warning C5041 'size': out-of-line definition for constexpr static data member is not needed and is deprecated in C++17:

struct X {
    static constexpr int size = 3;
};
const int X::size; // C5041

Avviso C4768 relativo a extern "C" __declspec(...) attivo per impostazione predefinitaextern "C" __declspec(...) warning C4768 now on by default

L'avviso è stato aggiunto in Visual Studio 2017 versione 15.3, ma è disattivato per impostazione predefinita.The warning was added in Visual Studio 2017 version 15.3 but was off by default. In Visual Studio 2017 versione 15.5 è attivo per impostazione predefinita.In Visual Studio 2017 version 15.5 it is on by default. Per altre informazioni, vedere Nuovo avviso per attributi declspec.See New warning on declspec attributes for more information.

Funzioni impostate come predefinite e __declspec(nothrow)Defaulted functions and __declspec(nothrow)

Il compilatore consentiva la dichiarazione delle funzioni impostate come predefinite con __declspec(nothrow) quando le corrispondenti funzioni di base/membro permettevano le eccezioni.The compiler previously allowed defaulted functions to be declared with __declspec(nothrow) when the corresponding base/member functions permitted exceptions. Questo comportamento è contrario allo standard C++ e può causare un comportamento non definito in fase di esecuzione.This behavior is contrary to the C++ Standard and can cause undefined behavior at runtime. Lo standard richiede che tali funzioni vengano definite come eliminate se è presente una specifica di eccezione non corrispondente.The standard requires such functions to be defined as deleted if there is an exception specification mismatch. In /std:c++17 il codice seguente genera l'errore C2280 tentativo di fare riferimento a una funzione eliminata. La funzione è stata eliminata in modo implicito perché la specifica dell'eccezione esplicita è incompatibile con quella della dichiarazione implicita.:Under /std:c++17, the following code raises C2280 attempting to reference a deleted function. Function was implicitly deleted because the explicit exception specification is incompatible with that of the implicit declaration.:

struct A {
    A& operator=(const A& other) { // No exception specification; this function may throw.
        ...
    }
};

struct B : public A {
    __declspec(nothrow) B& operator=(const B& other) = default;
};

int main()
{
    B b1, b2;
    b2 = b1; // error C2280
}

Per correggere questo codice, rimuovere __declspec(nothrow) dalla funzione impostata come predefinita o rimuovere = default e fornire una definizione per la funzione con qualsiasi gestione delle eccezioni obbligatorie:To correct this code, either remove __declspec(nothrow) from the defaulted function, or remove = default and provide a definition for the function along with any required exception handling:

struct A {
    A& operator=(const A& other) {
        ...
    }
};

struct B : public A {
    B& operator=(const B& other) = default;
};

int main()
{
    B b1, b2;
    b2 = b1;
}

noexcept e specializzazioni parzialinoexcept and partial specializations

Con noexcept nel sistema dei tipi, le specializzazioni parziali per la corrispondenza di determinati tipi disponibili per la chiamata potrebbero non essere compilate o non scegliere il modello primario a causa di una specializzazione parziale mancante per i puntatori alle funzioni noexcept.With noexcept in the type system, partial specializations for matching particular "callable" types may fail to compile or choose the primary template due to a missing partial specialization for pointers-to-noexcept-functions.

In questi casi potrebbe essere necessario aggiungere altre specializzazioni parziali per gestire i puntatori alle funzioni noexcept e i puntatori noexcept alle funzioni membro.In such cases, you may need to add additional partial specializations to handle the noexcept function pointers and noexcept pointers to member functions. Questi overload sono validi solo nella modalità /std:c++17.These overloads are only legal in /std:c++17 mode. Se è necessario mantenere la compatibilità con le versioni precedenti di C++14 e si sta scrivendo codice che verrà utilizzato da altri, è consigliabile proteggere questi nuovi overload in direttive #ifdef.If backwards-compatibility with C++14 must be maintained, and you are writing code that others will consume, then you should guard these new overloads inside #ifdef directives. Se si usa un modulo autonomo, invece di usare clausole guard #ifdef, è possibile eseguire solo la compilazione con l'opzione /Zc:noexceptTypes-.If you are working in a self-contained module, then instead of using #ifdef guards you can just compile with the /Zc:noexceptTypes- switch.

Il codice seguente esegue la compilazione in /std:c++14, ma ha esito negativo in /std:c++17 con l'errore C2027:uso del tipo non definito 'A':The following code compiles under /std:c++14 but fails under /std:c++17 with error C2027:use of undefined type 'A':

template <typename T> struct A;

template <>
struct A<void(*)()>
{
    static const bool value = true;
};

template <typename T>
bool g(T t)
{
    return A<T>::value;
}

void f() noexcept {}

int main()
{
    return g(&f) ? 0 : 1; // C2027
}

Il codice seguente ha esito positivo in /std:c++17 perché il compilatore sceglie la nuova specializzazione parziale A<void (*)() noexcept>:The following code succeeds under /std:c++17 because the compiler chooses the new partial specialization A<void (*)() noexcept>:

template <typename T> struct A;

template <>
struct A<void(*)()>
{
    static const bool value = true;
};

template <>
struct A<void(*)() noexcept>
{
    static const bool value = true;
};

template <typename T>
bool g(T t)
{
    return A<T>::value;
}

void f() noexcept {}

int main()
{
    return g(&f) ? 0 : 1; // OK
}

Vedere ancheSee Also

Conformità al linguaggio di Visual C++Visual C++ Language Conformance