Verbesserungen der C++-Konformität in Visual StudioC++ conformance improvements in Visual Studio

Microsoft C++ nimmt bei jedem Release Verbesserungen bei der Übereinstimmung mit Standards und Fehlerbehebungen vor.Microsoft C++ makes conformance improvements and bug fixes in every release. Dieser Artikel listet die Verbesserungen nach Hauptrelease und dann nach Versionen auf.This article lists the improvements by major release, then by version. Außerdem werden wichtige Fehlerbehebungen geordnet nach Version aufgeführt.It also lists major bug fixes by version. Um direkt zu den Änderungen für eine bestimmte Version zu gelangen, verwenden Sie die Liste In diesem Artikel.To jump directly to the changes for a specific version, use the In this article list.

Verbesserungen der Konformität in Visual Studio 2019 RTW (Version 16.0)Conformance improvements in Visual Studio 2019 RTW (version 16.0)

Visual Studio 2019 (RTW) enthält die folgenden Verbesserungen der Konformität, Fehlerbehebungen und Verhaltensänderungen des Microsoft C++-Compilers (MSVC).Visual Studio 2019 RTW contains the following conformance improvements, bug fixes, and behavior changes in the Microsoft C++ compiler (MSVC)

Hinweis: C++20-Features werden im Modus /std:c++latest zur Verfügung gestellt, bis die C++20-Implementierung für den Compiler und IntelliSense abgeschlossen ist.Note: C++20 features will be made available in /std:c++latest mode until the C++20 implementation is complete for both the compiler and IntelliSense. Zu diesem Zeitpunkt wird der Compilermodus /std:c++20 eingeführt.At that time, the /std:c++20 compiler mode will be introduced.

Verbesserte Unterstützung von Modulen für Vorlagen und die FehlererkennungImproved modules support for templates and error detection

Module entsprechen nun offiziell dem C++20-Standard.Modules are now officially in the C++20 standard. Die verbesserte Unterstützung wurde in Visual Studio 2017 Version 15.9 hinzugefügt.Improved support was added in Visual Studio 2017 version 15.9. Weitere Informationen finden Sie unter Better template support and error detection in C++ Modules with MSVC 2017 version 15.9 (Verbesserte Unterstützung von Vorlagen und Fehlererkennung in C++-Modulen mit MSVC 2017 Version 15.9).For more information, see Better template support and error detection in C++ Modules with MSVC 2017 version 15.9.

Geänderte Spezifikation des AggregattypsModified specification of aggregate type

Die Spezifikation von Aggregattypen wurde in C++20 geändert (siehe Prohibit aggregates with user-declared constructors (Verbieten von Aggregaten mit benutzerdeklarierten Konstruktoren)).The specification of an aggregate type has changed in C++20 (see Prohibit aggregates with user-declared constructors). In Visual Studio 2019 ist eine Klasse mit einem beliebigen benutzerdeklarierten Konstruktor (z. B. Einschließen von mit = default oder = delete deklarierten Konstruktoren) bei Verwendung von /std:c++latest kein Aggregat.In Visual Studio 2019, under /std:c++latest, a class with any user-declared constructor (for example, including a constructor declared = default or = delete) isn't an aggregate. Zuvor wurden Klassen nur durch von Benutzern bereitgestellte Konstruktoren als Aggregat disqualifiziert.Previously, only user-provided constructors would disqualify a class from being an aggregate. Diese Änderung führt weitere Einschränkungen für die Initialisierung solcher Typen ein.This change puts additional restrictions on how such types can be initialized.

Der folgende Code wird in Visual Studio 2017 fehlerfrei kompiliert, löst jedoch bei Verwendung von /std:c++latest die Fehler C2280 und C2440 in Visual Studio 2019 aus:The following code compiles without errors in Visual Studio 2017 but raises errors C2280 and C2440 in Visual Studio 2019 under /std:c++latest:

struct A
{
    A() = delete; // user-declared ctor
};

struct B
{
    B() = default; // user-declared ctor
    int i = 0;
};

A a{}; // ill-formed in C++20, previously well-formed
B b = { 1 }; // ill-formed in C++20, previously well-formed

Teilweise Unterstützung für operator <=>Partial support for operator <=>

P0515R3 C++20 führt den Operator für Dreiwegevergleiche <=> ein, der auch als „Raumschiffoperator“ bekannt ist.P0515R3 C++20 introduces the <=> three-way comparison operator, also known as the "spaceship operator". Visual Studio 2019 im /std:c++latest -Modus führt teilweise Unterstützung für den Operator ein, indem Fehler für die Syntax ausgelöst werden, die nun unzulässig ist.Visual Studio 2019 in /std:c++latest mode introduces partial support for the operator by raising errors for syntax that is now disallowed. Der folgende Code wird beispielsweise in Visual Studio 2017 fehlerfrei kompiliert, löst bei Verwendung von /std:c++latest in Visual Studio 2019 jedoch mehrere Fehler aus:For example, the following code compiles without errors in Visual Studio 2017 but raises multiple errors in Visual Studio 2019 under /std:c++latest:

struct S
{
    bool operator<=(const S&) const { return true; }
};

template <bool (S::*)(const S&) const>
struct U { };

int main(int argc, char** argv)
{
    U<&S::operator<=> u; // In Visual Studio 2019 raises C2039, 2065, 2146.
}

Fügen Sie ein Leerzeichen in die betroffene Zeile vor der letzten spitzen Klammer ein, um die Fehler zu vermeiden: U<&S::operator<= > u;.To avoid the errors, insert a space in the offending line before the final angle bracket: U<&S::operator<= > u;.

Verweise auf Typen mit nicht übereinstimmenden CV-QualifizierernReferences to types with mismatched cv-qualifiers

MSVC hat zuvor die direkte Einbindung von Verweisen auf einen Typ mit nicht übereinstimmenden CV-Qualifizierern unter der obersten Ebene zugelassen.Previously, MSVC allowed direct binding of a reference from a type with mismatched cv-qualifiers below the top level. Diese Bindung kann die Änderung von vermeintlichen const-Daten ermöglichen, auf die sich der Verweis bezieht.This binding could allow modification of supposedly const data referred to by the reference. Der Compiler erstellt jetzt gemäß den Anforderung des Standards einen temporären Wert.The compiler now creates a temporary, as required by the standard. In Visual Studio 2017 wird der folgende Code ohne Warnungen kompiliert.In Visual Studio 2017, the following code compiles without warnings. In Visual Studio 2019 löst der Compiler die Warnung „C4172: <func:#1 "?PData@X@@QBEABQBXXZ"> returning address of local variable or temporary.“ aus:In Visual Studio 2019, the compiler raises warning C4172: <func:#1 "?PData@X@@QBEABQBXXZ"> returning address of local variable or temporary.:

struct X
{
    const void* const& PData() const
    {
        return _pv;
    }

    void* _pv;
};

int main()
{
    X x;
    auto p = x.PData(); // C4172
}

Der Operator reinterpret_cast einer überladenen Funktionreinterpret_cast from an overloaded function

Das Argument für reinterpret_cast ist keiner der Kontexte, in denen die Adresse einer überladenen Funktion zulässig ist.The argument to reinterpret_cast isn't one of the contexts in which the address of an overloaded function is permitted. Der folgende Code wird in Visual Studio 2017 fehlerfrei kompiliert, in Visual Studio 2019 wird jedoch der Fehler „C2440: cannot convert from 'overloaded-function' to 'fp'“ ausgelöst:The following code compiles without errors in Visual Studio 2017, but in Visual Studio 2019 it raises error C2440: cannot convert from 'overloaded-function' to 'fp':

int f(int) { return 1; }
int f(float) { return .1f; }
using fp = int(*)(int);

int main()
{
    fp r = reinterpret_cast<fp>(&f);
}

Verwenden Sie für dieses Szenario eine zulässige Umwandlung, um den Fehler zu vermeiden:To avoid the error, use an allowed cast for this scenario:

int f(int);
int f(float);
using fp = int(*)(int);

int main()
{
    fp r = static_cast<fp>(&f); // or just &f;
}

Lambda-ClosuresLambda closures

In C++14 sind Lambda-Closure-Typen nicht literal.In C++14, lambda closure types aren't literals. Die primäre Folge dieser Regel ist, dass ein Lambda keinen constexpr -Variablen zugewiesen werden kann.The primary consequence of this rule is that a lambda may not be assigned to a constexpr variable. Der folgende Code wird in Visual Studio 2017 fehlerfrei kompiliert, in Visual Studio 2019 wird jedoch der Fehler „C2127: 'l': illegal initialization of 'constexpr' entity with a non-constant expression“ ausgelöst:The following code compiles without errors in Visual Studio 2017, but in Visual Studio 2019 it raises error C2127: 'l': illegal initialization of 'constexpr' entity with a non-constant expression:

int main()
{
    constexpr auto l = [] {}; // C2127 in VS2019
}

Entfernen Sie entweder den constexpr -Qualifizierer, oder ändern Sie den Konformitätsmodus in /std:c++17, um diesen Fehler zu vermeiden.To avoid the error, either remove the constexpr qualifier, or else change the conformance mode to /std:c++17.

std::create_directory-Fehlercodesstd::create_directory failure codes

P1164 des C++20-Standards wurde bedingungslos implementiert.Implemented P1164 from C++20 unconditionally. Dadurch wurde std::create_directory so geändert, dass überprüft wird, ob das Ziel beim Auftreten des Fehlers bereits ein Verzeichnis war.This changes std::create_directory to check whether the target was already a directory on failure. Zuvor wurden alle Fehler vom Typ ERROR_ALREADY_EXISTS in erfolgreiche Codes umgewandelt, die jedoch kein Verzeichnis erstellt haben.Previously, all ERROR_ALREADY_EXISTS type errors were turned into success-but-directory-not-created codes.

operator<<(std::ostream, nullptr_t)

Gemäß LWG 2221 wurde operator<<(std::ostream, nullptr_t) zum Schreiben von nullptrs in Streams hinzugefügt.Per LWG 2221, added operator<<(std::ostream, nullptr_t) for writing nullptrs to streams.

Zusätzliche parallele AlgorithmenAdditional parallel algorithms

Neue parallele Versionen von is_sorted, is_sorted_until, is_partitioned, set_difference, set_intersection, is_heap und is_heap_until wurden hinzugefügt.New parallel versions of is_sorted, is_sorted_until, is_partitioned, set_difference, set_intersection, is_heap, and is_heap_until.

Atomische Initialisierungatomic initialization

P0883 "Fixing atomic initialization" (Beheben der atomischen Initialisierung) ändert std::atomic in die Initialisierung des enthaltenen Werts von T, anstatt eine Standardinitialisierung durchzuführen.P0883 "Fixing atomic initialization" changes std::atomic to value-initialize the contained T rather than default-initializing it. Die Behebung wird aktiviert, wenn Clang/LLVM mit der Microsoft-Standardbibliothek verwendet wird.The fix is enabled when using Clang/LLVM with the Microsoft standard library. Sie ist derzeit für den C++-Compiler von Microsoft als Workaround für einen Fehler in der Verarbeitung von constexpr deaktiviert.It's currently disabled for the Microsoft C++ compiler, as a workaround for a bug in constexpr processing.

remove_cvref und remove_cvref_tremove_cvref and remove_cvref_t

Die Typmerkmale remove_cvref und remove_cvref_t aus P0550 wurden implementiert.Implemented the remove_cvref and remove_cvref_t type traits from P0550. Diese entfernen die reference- und CV-Qualifizierer eines Typs ohne verfallende Funktionen und Arrays in Zeigern (im Gegensatz zu std::decay und std::decay_t).These remove reference-ness and cv-qualification from a type without decaying functions and arrays to pointers (unlike std::decay and std::decay_t).

Makros für FeaturetestsFeature-test macros

Die Entwicklung der Featuretestmakros (P0941R2) ist nun abgeschlossen. Dadurch wird __has_cpp_attribute unterstützt.P0941R2 - feature-test macros is complete, with support for __has_cpp_attribute. Featuretestmakros werden in allen Standardmodi unterstützt.Feature-test macros are supported in all standard modes.

Unterbinden von Aggregaten mit benutzerdeklarierten KonstruktorenProhibit aggregates with user-declared constructors

C++20 P1008R1 - prohibiting aggregates with user-declared constructors (Unterbinden von Aggregaten mit benutzerdeklarierten Konstruktoren) ist abgeschlossen.C++20 P1008R1 - prohibiting aggregates with user-declared constructors is complete.

Verbesserungen der Konformität in 16.1Conformance improvements in 16.1

char8_tchar8_t

P0482r6.P0482r6. C++20 führt einen neuen Zeichentyp ein, der für die Darstellung von UTF-8-Codeeinheiten verwendet wird.C++20 adds a new character type that is used to represent UTF-8 code units. u8-Zeichenfolgenliterale in C++20 verfügen über den Typ const char8_t[N] anstelle von const char[N] (der vorherige Typ).u8 string literals in C++20 have type const char8_t[N] instead of const char[N], which was the case previously. Ähnliche Änderungen wurden in N2231 für den C-Standard vorgeschlagen.Similar changes have been proposed for the C standard in N2231. Vorschläge für die Wiederherstellung der Abwärtskompatibilität von char8_t finden Sie in P1423r3.Suggestions for char8_t backward compatibility remediation are given in P1423r3. In Visual Studio 2019 Version 16.1 fügt der C++-Compiler von Microsoft Unterstützung für char8_t hinzu, wenn die Compileroption /Zc:char8_t angegeben wird.The Microsoft C++ compiler adds support for char8_t in Visual Studio 2019 version 16.1 when you specify the /Zc:char8_t compiler option. Zukünftig erfolgt die Unterstützung mit /std:c++latest, was mithilfe von /Zc:char8_t- in das C++17-Verhalten zurückversetzt werden kann.In the future, it will be supported with /std:c++latest, which can be reverted to C++17 behavior via /Zc:char8_t-. Der EDG-Compiler, der IntelliSense betreibt, unterstützt dies noch nicht, weshalb vermeidbare Intune-spezifische Fehler auftreten, die sich nicht auf die tatsächliche Kompilierung auswirken.The EDG compiler that powers IntelliSense doesn't yet support it, so you'll see spurious IntelliSense-only errors that don't impact the actual compilation.

BeispielExample

const char* s = u8"Hello"; // C++17
const char8_t* s = u8"Hello"; // C++20

Die std::type_identity-Metafunktion und das std::identity-Funktionsobjektstd::type_identity metafunction and std::identity function object

P0887R1 type_identity.P0887R1 type_identity. Die veraltete std::identity-Klassenvorlagenerweiterung wurde entfernt und durch die std::type_identity-Metafunktion und das std::identity-Funktionsobjekt von C++20 ersetzt.The deprecated std::identity class template extension has been removed, and replaced with the C++20 std::type_identity metafunction and std::identity function object. Beides ist nur in /std:c++latest verfügbar.Both are available only under /std:c++latest.

Im folgenden Beispiel wird die Veraltungswarnung C4996 für std::identity (in <type_traits> definiert) in Visual Studio 2017 erzeugt:The following example produces deprecation warning C4996 for std::identity (defined in <type_traits>) in Visual Studio 2017:

#include <type_traits>

using T = std::identity<int>::type;
T x, y = std::identity<T>{}(x);
int i = 42;
long j = std::identity<long>{}(i);

Im folgenden Beispiel wird die Verwendung des neuen std::identity-Funktionsobjekts (in <functional> definiert) gemeinsam mit der neuen std::type_identity-Metafunktion veranschaulicht:The following example shows how to use the new std::identity (defined in <functional>) together with the new std::type_identity:

#include <type_traits>
#include <functional>

using T = std::type_identity<int>::type;
T x, y = std::identity{}(x);
int i = 42;
long j = static_cast<long>(i);

Syntaxprüfung für generische LambdasSyntax checks for generic lambdas

Die neue Lambdaverarbeitung ermöglicht im Konformitätsmodus einige syntaktische Überprüfungen in generischen Lambdas bei Verwendung von /std:c++latest oder anderen Sprachmodi mit /experimental:newLambdaProcessor .The new lambda processor enables some conformance-mode syntactic checks in generic lambdas, under /std:c++latest or under any other language mode with /experimental:newLambdaProcessor.

Dieser Code wird in Visual Studio 2017 fehlerfrei kompiliert, erzeugt in Visual Studio 2019 jedoch den Fehler „C2760 syntax error: unexpected token '\<id-expr>', expected 'id-expression'“:In Visual Studio 2017, this code compiles without warnings, but in Visual Studio 2019 it produces error C2760 syntax error: unexpected token '\<id-expr>', expected 'id-expression':

void f() {
    auto a = [](auto arg) {
        decltype(arg)::Type t;
    };
}

Im folgenden Beispiel wird die richtige Syntax veranschaulicht, die nun vom Compiler erzwungen wird:The following example shows the correct syntax, now enforced by the compiler:

void f() {
    auto a = [](auto arg) {
        typename decltype(arg)::Type t;
    };
}

Argumentbezogene Suchen nach FunktionsaufrufenArgument-dependent lookup for function calls

P0846R0 (C++20) Die Möglichkeit, Funktionsvorlagen über argumentbezogene Suchen nach Funktionsaufrufausdrücken zu suchen, wurde mit expliziten Vorlagenargumenten erweitert.P0846R0 (C++20) Increased ability to find function templates via argument-dependent lookup for function-call expressions with explicit template arguments. Erfordert /std:c++latest .Requires /std:c++latest.

Designierte InitialisierungDesignated initialization

P0329R4 (C++20) Die designierte Initialisierung ermöglicht, dass bestimmte Member in der Aggregatinitialisierung mithilfe der Type t { .member = expr }-Syntax ausgewählt werden können.P0329R4 (C++20) Designated initialization allows specific members to be selected in aggregate initialization by using the Type t { .member = expr } syntax. Erfordert /std:c++latest .Requires /std:c++latest.

Neue und aktualisierte Standardbibliotheksfunktionen (C++20)New and updated standard library functions (C++20)

  • starts_with() und ends_with() für basic_string und basic_string_view.starts_with() and ends_with() for basic_string and basic_string_view.
  • contains() für assoziative Container.contains() for associative containers.
  • remove(), remove_if() und unique() für list und forward_list geben nun size_type zurück.remove(), remove_if(), and unique() for list and forward_list now return size_type.
  • shift_left() und shift_right() wurden <algorithm> hinzugefügt.shift_left() and shift_right() added to <algorithm>.

Verbesserungen der Konformität in 16.2Conformance improvements in 16.2

noexcept constexpr-Funktionennoexcept constexpr functions

Constexpr-Funktionen werden bei Verwendung in einem konstanten Ausdruck nicht mehr standardmäßig als noexcept angesehen.Constexpr functions are no longer considered noexcept by default when used in a constant expression. Dieser Behavior Change stammt aus der Auflösung von CWG 1351 und ist in /permissive- aktiviert.This behavior change comes from the resolution of CWG 1351 and is enabled in /permissive-. Das folgende Beispiel wird in Visual Studio 2019 Version 16.1 und früher kompiliert, erzeugt jedoch C2338 in Visual Studio 2019 Version 16.2:The following example compiles in Visual Studio 2019 version 16.1 and earlier, but produces C2338 in Visual Studio 2019 version 16.2:

constexpr int f() { return 0; }

int main() {
    static_assert(noexcept(f()), "f should be noexcept"); // C2338 in 16.2
}

Fügen Sie den Ausdruck noexcept zur Funktionsdeklaration hinzu, um den Fehler zu beheben:To fix the error, add the noexcept expression to the function declaration:

constexpr int f() noexcept { return 0; }

int main() {
    static_assert(noexcept(f()), "f should be noexcept");
}

Binäre Ausdrücke mit unterschiedlichen EnumerationstypenBinary expressions with different enum types

Arithmetischen Konvertierungen für Operanden, bei denen einer ein Enumerationstyp und der andere ein anderer Enumerationstyp oder ein Gleitkommatyp ist, werden in C++20 (P1120R0) als veraltet eingestuft.The ability to apply the usual arithmetic conversions on operands, where one is of enumeration type, and the other is of a different enumeration type or a floating-point type, is deprecated in C++20 (P1120R0).

In Visual Studio 2019 Version 16.2 und höher erzeugt der folgende Code eine Warnung der Stufe 4, wenn die Compileroption /std:c++latest aktiviert ist:In Visual Studio 2019 version 16.2 and later, the following code produces a level 4 warning when the /std:c++latest compiler option is enabled:

enum E1 { a };
enum E2 { b };
int main() {
    int i = a | b; // warning C5054: operator '|': deprecated between enumerations of different types
}

Konvertieren Sie den zweiten Operanden mit static_cast, um zu vermeiden, dass eine Warnung ausgelöst wird:To avoid the warning, use static_cast to convert the second operand:

enum E1 { a };
enum E2 { b };
int main() {
  int i = a | static_cast<int>(b);
}

Das heißt, die Verwendung einer binären Operation zwischen einem Enumerations- und einem Gleitkommatyp löst jetzt eine Warnung aus, wenn die Compileroption /std:c++latest aktiviert ist:Using a binary operation between an enumeration and a floating-point type is now a warning when the /std:c++latest compiler option is enabled:

enum E1 { a };
int main() {
  double i = a * 1.1;
}

Konvertieren Sie den zweiten Operanden mit static_cast, um zu vermeiden, dass eine Warnung ausgelöst wird:To avoid the warning, use static_cast to convert the second operand:

enum E1 { a };
int main() {
   double i = static_cast<int>(a) * 1.1;
}

Gleichheitsvergleiche und relationale Vergleiche von ArraysEquality and relational comparisons of arrays

Gleichheitsvergleiche und relationale Vergleiche zwischen zwei Operanden des Arraytyps werden in C++20 (P1120R0) als veraltet eingestuft.Equality and relational comparisons between two operands of array type are deprecated in C++20 (P1120R0). Das heißt, dass ein Vergleichsvorgang zwischen zwei Arrays (trotz des Rangs und der Ähnlichkeiten der Erweiterung) jetzt eine Warnung auslöst.In other words, a comparison operation between two arrays (despite rank and extent similarities) is now a warning. Ab Visual Studio 2019 Version 16.2 erzeugt der folgende Code die Meldung „C5056: operator '==': deprecated for array types“, wenn die Compileroption /std:c++latest aktiviert ist:Starting in Visual Studio 2019 version 16.2, the following code produces C5056: operator '==': deprecated for array types when the /std:c++latest compiler option is enabled:

int main() {
    int a[] = { 1, 2, 3 };
    int b[] = { 1, 2, 3 };
    if (a == b) { return 1; }
}

Sie können die Adressen der ersten Elemente vergleichen, um zu vermeiden, dass eine Warnung ausgelöst wird:To avoid the warning, you can compare the addresses of the first elements:

int main() {
    int a[] = { 1, 2, 3 };
    int b[] = { 1, 2, 3 };
    if (&a[0] == &b[0]) { return 1; }
}

Sie können ermitteln, ob der Inhalt von zwei Arrays gleich ist, indem Sie die std::equal-Funktion verwenden:To determine whether the contents of two arrays are equal, use the std::equal function:

std::equal(std::begin(a), std::end(a), std::begin(b), std::end(b));

Auswirkung der Definition des Spaceship-Operators auf == und !=Effect of defining spaceship operator on == and !=

Eine Definition des Spaceship-Operators ( <=> ) allein schreibt keine Ausdrücke mit == oder != mehr neu, es sei denn, der Spaceship-Operator ist als = default (P1185R2) markiert.A definition of the spaceship operator (<=>) alone will no longer rewrite expressions involving == or != unless the spaceship operator is marked as = default (P1185R2). Das folgende Beispiel wird in Visual Studio 2019 RTW und Version 16.1 kompiliert, erzeugt jedoch C2678 in Visual Studio 2019 Version 16.2:The following example compiles in Visual Studio 2019 RTW and version 16.1, but produces C2678 in Visual Studio 2019 version 16.2:

#include <compare>

struct S {
  int a;
  auto operator<=>(const S& rhs) const {
    return a <=> rhs.a;
  }
};
bool eq(const S& lhs, const S& rhs) {
  return lhs == rhs;
}
bool neq(const S& lhs, const S& rhs) {
    return lhs != rhs;
}

Sie können diesen Fehler vermeiden, indem Sie den Operator == definieren oder als Standard deklarieren:To avoid the error, define the operator== or declare it as defaulted:

#include <compare>

struct S {
  int a;
  auto operator<=>(const S& rhs) const {
    return a <=> rhs.a;
  }
  bool operator==(const S&) const = default;
};
bool eq(const S& lhs, const S& rhs) {
  return lhs == rhs;
}
bool neq(const S& lhs, const S& rhs) {
    return lhs != rhs;
}

Verbesserungen der StandardbibliothekStandard Library improvements

  • <charconv> to_chars() mit fester/wissenschaftlicher Genauigkeit<charconv> to_chars() with fixed/scientific precision. (Die allgemeine Genauigkeit ist derzeit für Version 16.4 geplant.)(General precision is currently planned for 16.4.)
  • P0020R6: atomic<float>, atomic<double>, atomic<long double>P0020R6: atomic<float>, atomic<double>, atomic<long double>
  • P0463R1: endianP0463R1: endian
  • P0482R6: Bibliotheksunterstützung für char8_tP0482R6: Library Support For char8_t
  • P0600R1: [[nodiscard]]Für STL, Teil 1P0600R1: [[nodiscard]] For The STL, Part 1
  • P0653R2: to_address()P0653R2: to_address()
  • P0754R2: <version>P0754R2: <version>
  • P0771R1: noexcept für Bewegungskonstruktor von std::functionP0771R1: noexcept For std::function's move constructor

Verbesserungen der Konformität in Visual Studio 2019, Version 16.3Conformance improvements in Visual Studio 2019 version 16.3

Streamextraktionsoperatoren für char* entferntStream extraction operators for char* removed

Die Streamextraktionsoperatoren für Zeiger auf Zeichen wurden entfernt und durch Extraktionsoperatoren für Arrayzeichen ersetzt (vgl. P0487R1).Stream extraction operators for pointer-to-characters have been removed and replaced by extraction operators for array-of-characters (per P0487R1). WG21 betrachtet die entfernten Überladungen als unsicher.WG21 considers the removed overloads to be unsafe. Im /std:c++latest-Modus löst das folgende Beispiel jetzt „C2679: binary '>>': no operator found which takes a right-hand operand of type 'char*' (or there is no acceptable conversion)“ aus:In /std:c++latest mode, the following example now produces C2679: binary '>>': no operator found which takes a right-hand operand of type 'char*' (or there is no acceptable conversion):

   char x[42];
   char* p = x;
   std::cin >> std::setw(42);
   std::cin >> p;

Sie können den Fehler vermeiden, indem Sie den Extraktionsoperator mit einer char[]-Variablen verwenden:To avoid the error, use the extraction operator with a char[] variable:

char x[42];
std::cin >> x;

Neue Schlüsselwörter requires und conceptNew keywords requires and concept

Die neuen Schlüsselwörter requires und concept wurden zum Microsoft C++-Compiler hinzugefügt.New keywords requires and concept have been added to the Microsoft C++ compiler. Wenn Sie versuchen, eins dieser Schlüsselwörter als Bezeichner im Modus /std:c++latest zu verwenden, löst der Compiler den Fehler „C2059: syntax error“ aus.If you attempt to use either one as an identifier in /std:c++latest mode, the compiler will raise C2059: syntax error.

Konstruktoren als Typnamen nicht zulässigConstructors as type names disallowed

Konstruktornamen werden nicht mehr als injizierte Klassennamen betrachtet, wenn Sie in einem qualifizierten Namen nach einem Alias für eine Spezialisierung einer Klassenvorlage angezeigt werden.Constructor names are no longer considered injected-class-names when they appear in a qualified name after an alias to a class template specialization. Dies ermöglichte zuvor die Verwendung von Konstruktoren als Typnamen, um andere Entitäten zu deklarieren.Previously, it allowed the use of constructors as a type name to declare other entities. Mit dem folgenden Beispiel wird nun der Fehler „C3646: 'TotalDuration': unknown override specifier“ ausgelöst:The following example now produces C3646: 'TotalDuration': unknown override specifier:

#include <chrono>

class Foo {
   std::chrono::milliseconds::duration TotalDuration{};
};

Sie können den Fehler vermeiden, indem wie im Folgenden gezeigt TotalDuration deklarieren:To avoid the error, declare TotalDuration as shown here:

#include <chrono>

class Foo {
  std::chrono::milliseconds TotalDuration {};
};

Strengere Überprüfung von extern "C"-FunktionenStricter checking of extern "C" functions

Wenn eine extern "C" -Funktion in verschiedenen Namespaces deklariert wurde, haben frühere Versionen des Microsoft C++-Compilers nicht überprüft, ob die Deklarationen kompatibel waren.If an extern "C" function was declared in different namespaces, previous versions of the Microsoft C++ compiler didn't check whether the declarations were compatible. In Visual Studio 2019, Version 16.3 führt der Compiler eine solche Prüfung durch.In Visual Studio 2019 version 16.3, the compiler performs such a check. Im Modus /permissive- löst der folgende Code die Fehler „C2371 redefinition; different basic types“ und „C2733 you cannot overload a function with C linkage“ aus:In /permissive- mode, the following code produces errors C2371 redefinition; different basic types and C2733 you cannot overload a function with C linkage:

using BOOL = int;

namespace N
{
   extern "C" void f(int, int, int, bool);
}

void g()
{
   N::f(0, 1, 2, false);
}

extern "C" void f(int, int, int, BOOL){}

Sie können die Fehler im vorherigen Beispiel vermeiden, indem Sie konsistent bool anstelle von BOOL in beiden Deklarationen von f verwenden.To avoid the errors in the previous example, use bool instead of BOOL consistently in both declarations of f.

Verbesserungen der StandardbibliothekStandard Library improvements

Die nicht standardmäßigen Header <stdexcpt.h> und <typeinfo.h> wurden entfernt.The non-standard headers <stdexcpt.h> and <typeinfo.h> have been removed. Code, der diese enthält, sollte stattdessen jeweils die standardmäßigen Header <exception> und <typeinfo> enthalten.Code that includes them should instead include the standard headers <exception> and <typeinfo>, respectively.

Verbesserungen der Konformität in Visual Studio 2019, Version 16.4Conformance improvements in Visual Studio 2019 version 16.4

Bessere Durchsetzung der zweiphasigen Namenssuche für qualified-ids in /permissive-Better enforcement of two-phase name lookup for qualified-ids in /permissive-

Die Zweiphasennamenssuche erfordert, dass nicht abhängige Namen in Vorlagentexten zum Zeitpunkt der Definition für die Vorlage sichtbar sind.Two-phase name lookup requires that non-dependent names used in template bodies must be visible to the template at definition time. Zuvor wurden solche Namen gefunden, wenn die Vorlage instanziiert wurde.Previously, such names may have been found when the template is instantiated. Diese Änderung vereinfacht das Schreiben von portierbarem, konformem Code in MSVC bei Verwendung des Flags /permissive-.This change makes it easier to write portable and conforming code in MSVC under the /permissive- flag.

Wenn in Visual Studio 2019, Version 16.4, das Flag /permissive- festgelegt ist, erzeugt das folgende Beispiel einen Fehler, weil N::f beim Definieren der Vorlage f<T> nicht sichtbar ist:In Visual Studio 2019 version 16.4 with the /permissive- flag set, the following example produces an error, because N::f isn't visible when the f<T> template is defined:

template <class T>
int f() {
    return N::f() + T{}; // error C2039: 'f': is not a member of 'N'
}

namespace N {
    int f() { return 42; }
}

In der Regel lässt sich dieser Fehler durch Einschließen fehlender Header oder Vorausdeklarieren von Funktionen oder Variablen beheben, wie im folgenden Beispiel gezeigt:Typically, this error can be fixed by including missing headers or forward-declaring functions or variables, as shown in the following example:

namespace N {
    int f();
}

template <class T>
int f() {
    return N::f() + T{};
}

namespace N {
    int f() { return 42; }
}

Implizite Konvertierung integraler konstanter Ausdrücke in NULL-ZeigerImplicit conversion of integral constant expressions to null pointer

Der MSVC-Compiler implementiert jetzt CWG Issue 903 im Konformitätsmodus ( /permissive- ).The MSVC compiler now implements CWG Issue 903 in conformance mode (/permissive-). Diese Regel lässt keine implizite Konvertierung von integralen konstanten Ausdrücken (mit Ausnahme des Integerliterals „0“) in NULL-Zeiger-Konstanten zu.This rule disallows implicit conversion of integral constant expressions (except for the integer literal '0') to null pointer constants. Das folgende Beispiel erzeugt C2440 im Konformitätsmodus:The following example produces C2440 in conformance mode:

int* f(bool* p) {
    p = false; // error C2440: '=': cannot convert from 'bool' to 'bool *'
    p = 0; // OK
    return false; // error C2440: 'return': cannot convert from 'bool' to 'int *'
}

Verwenden Sie zur Behebung des Fehlers nullptr anstelle von false .To fix the error, use nullptr instead of false. Das Literal „0“ ist weiterhin erlaubt:A literal 0 is still allowed:

int* f(bool* p) {
    p = nullptr; // OK
    p = 0; // OK
    return nullptr; // OK
}

Standardregeln für Typen von IntegerliteralenStandard rules for types of integer literals

Im Konformitätsmodus (aktiviert durch /permissive-) verwendet MSVC die Standardregeln für Typen von Integerliteralen.In conformance mode (enabled by /permissive-), MSVC uses the standard rules for types of integer literals. Dezimalliteralen, die zu groß für einen signed int -Typ sind, wurde früher der Typ unsigned int zugewiesen.Decimal literals too large to fit in a signed int were previously given type unsigned int. Jetzt erhalten solche Literale den nächstgrößeren signed -Integertyp: long long .Now such literals are given the next largest signed integer type, long long. Darüber hinaus wird Literalen mit dem Suffix „ll“, die zu groß für einen signed -Typ sind, der Typ unsigned long long zugewiesen.Additionally, literals with the 'll' suffix that are too large to fit in a signed type are given type unsigned long long.

Dies kann dazu führen, dass verschiedene Warnungsdiagnosen generiert werden und Unterschiede im Verhalten bei arithmetischen Operationen in Literalen auftreten.This change can lead to different warning diagnostics being generated, and behavior differences for arithmetic operations on literals.

Das folgende Beispiel zeigt das neue Verhalten in Visual Studio 2019, Version 16.4.The following example shows the new behavior in Visual Studio 2019 version 16.4. Die Variable i weist jetzt den Typ unsigned int auf.The i variable is now of type unsigned int. Aus diesem Grund wird die Warnung ausgelöst.That's why the warning is raised. Die höchstwertigen Bits der Variable j werden auf 0 festgelegt.The high-order bits of the variable j are set to 0.

void f(int r) {
    int i = 2964557531; // warning C4309: truncation of constant value
    long long j = 0x8000000000000000ll >> r; // literal is now unsigned, shift will fill high-order bits with 0
}

Das folgende Beispiel zeigt, wie Sie das alte Verhalten beibehalten und Warnungen und die Verhaltensänderung zur Laufzeit vermeiden:The following example demonstrates how to keep the old behavior and avoid the warnings and run-time behavior change:

void f(int r) {
int i = 2964557531u; // OK
long long j = (long long)0x8000000000000000ll >> r; // shift will keep high-order bits
}

Funktionsparameter, die ein Shadowing für Vorlagenparameter durchführenFunction parameters that shadow template parameters

Der MSVC-Compiler löst jetzt einen Fehler aus, wenn ein Funktionsparameter ein Shadowing für einen Vorlagenparameter durchführt:The MSVC compiler now raises an error when a function parameter shadows a template parameter:

template<typename T>
void f(T* buffer, int size, int& size_read);

template<typename T, int Size>
void f(T(&buffer)[Size], int& Size) // error C7576: declaration of 'Size' shadows a template parameter
{
    return f(buffer, Size, Size);
}

Um den Fehler zu beheben, ändern Sie Namen eines der Parameter:To fix the error, change the name of one of the parameters:

template<typename T>
void f(T* buffer, int size, int& size_read);

template<typename T, int Size>
void f(T (&buffer)[Size], int& size_read)
{
    return f(buffer, Size, size_read);
}

Vom Benutzer bereitgestellte Spezialisierungen von TypmerkmalenUser-provided specializations of type traits

In Übereinstimmung mit der Unterklausel meta.rqmts der Standardversion löst der MSVC-Compiler jetzt einen Fehler aus, wenn eine benutzerdefinierte Spezialisierung einer der angegebenen type_traits-Vorlagen im Namespace std gefunden wird.In compliance with the meta.rqmts subclause of the Standard, the MSVC compiler now raises an error when it encounters a user-defined specialization of one of the specified type_traits templates in the std namespace. Sofern nicht anders angegeben, führen solche Spezialisierungen zu nicht definiertem Verhalten.Unless otherwise specified, such specializations result in undefined behavior. Das folgende Beispiel zeigt ein nicht definiertes Verhalten, weil es die Regel verletzt, und bei static_assert tritt der Fehler C2338 auf.The following example has undefined behavior because it violates the rule, and the static_assert fails with error C2338.

#include <type_traits>
struct S;

template<>
struct std::is_fundamental<S> : std::true_type {};

static_assert(std::is_fundamental<S>::value, "fail");

Definieren Sie eine Struktur, die vom bevorzugten type_trait-Element erbt, und legen Sie Folgendes fest, um den Fehler zu vermeiden:To avoid the error, define a struct that inherits from the preferred type_trait, and specialize that:

#include <type_traits>

struct S;

template<typename T>
struct my_is_fundamental : std::is_fundamental<T> {};

template<>
struct my_is_fundamental<S> : std::true_type { };

static_assert(my_is_fundamental<S>::value, "fail");

Änderungen an vom Compiler bereitgestellten VergleichsoperatorenChanges to compiler-provided comparison operators

Der MSVC-Compiler implementiert jetzt die folgenden Änderungen an Vergleichsoperatoren gemäß P1630R1, wenn die Option /std:c++latest aktiviert ist:The MSVC compiler now implements the following changes to comparison operators per P1630R1 when the /std:c++latest option is enabled:

Der Compiler schreibt Ausdrücke nicht mehr mithilfe von operator== neu, wenn diese einen Rückgabetyp beinhalten, der kein bool -Wert ist.The compiler no longer rewrites expressions using operator== if they involve a return type that isn't a bool. Mit dem folgenden Code wird nun der Fehler „C2088: '!=': illegal for struct“ generiert:The following code now produces error C2088: '!=': illegal for struct:

struct U {
    operator bool() const;
};

struct S {
    U operator==(const S&) const;
};

bool neq(const S& lhs, const S& rhs) {
    return lhs != rhs;
}

Um diesen Fehler zu vermeiden, müssen Sie den erforderlichen Operator explizit definieren:To avoid the error, you must explicitly define the needed operator:

struct U {
    operator bool() const;
};

struct S {
    U operator==(const S&) const;
    U operator!=(const S&) const;
};

bool neq(const S& lhs, const S& rhs) {
    return lhs != rhs;
}

Der Compiler definiert keinen Standardvergleichsoperator mehr, wenn es sich um einen Member einer union-ähnlichen Klasse handelt.The compiler no longer defines a defaulted comparison operator if it's a member of a union-like class. Mit dem folgenden Beispiel wird nun der Fehler „C2120: 'void' illegal with all types“ generiert:The following example now produces error C2120: 'void' illegal with all types:

#include <compare>

union S {
    int a;
    char b;
    auto operator<=>(const S&) const = default;
};

bool lt(const S& lhs, const S& rhs) {
    return lhs < rhs;
}

Um diesen Fehler zu vermeiden, definieren Sie einen Text für den Operator:To avoid the error, define a body for the operator:

#include <compare>

union S {
    int a;
    char b;
    auto operator<=>(const S&) const { ... }
};

bool lt(const S& lhs, const S& rhs) {
    return lhs < rhs;
}

Der Compiler definiert keinen standardmäßigen Vergleichsoperator mehr, wenn die Klasse einen Verweismember enthält.The compiler will no longer define a defaulted comparison operator if the class contains a reference member. Mit dem folgenden Code wird nun der Fehler „C2120: 'void' illegal with all types“ generiert:The following code now produces error C2120: 'void' illegal with all types:

#include <compare>

struct U {
    int& a;
    auto operator<=>(const U&) const = default;
};

bool lt(const U& lhs, const U& rhs) {
    return lhs < rhs;
}

Um diesen Fehler zu vermeiden, definieren Sie einen Text für den Operator:To avoid the error, define a body for the operator:

#include <compare>

struct U {
    int& a;
    auto operator<=>(const U&) const { ... };
};

bool lt(const U& lhs, const U& rhs) {
    return lhs < rhs;
}

Verbesserungen der Konformität in Visual Studio 2019, Version 16.5Conformance improvements in Visual Studio 2019 version 16.5

Eine explizite Spezialisierungsdeklaration ohne Initialisierer ist keine DefinitionExplicit specialization declaration without an initializer isn't a definition

Unter /permissive- erzwingt MSVC jetzt eine Standardregel, die besagt, dass explizite Spezialisierungsdeklarationen ohne Initialisierer keine Definitionen sind.Under /permissive-, MSVC now enforces a standard rule that explicit specialization declarations without initializers aren't definitions. Zuvor galt die Deklaration als Definition mit einem Standardinitialisierer.Previously, the declaration would be considered a definition with a default-initializer. Der Effekt kann zum Zeitpunkt der Verknüpfung beobachtet werden, da ein Programm, das von diesem Verhalten abhängig ist, nun nicht aufgelöste Symbole aufweisen kann.The effect is observable at link time, since a program depending on this behavior may now have unresolved symbols. Dieses Beispiel führt jetzt zu einem Fehler:This example now results in an error:

template <typename> struct S {
    static int a;
};

// In permissive-, this declaration isn't a definition, and the program won't link.
template <> int S<char>::a;

int main() {
    return S<char>::a;
}
error LNK2019: unresolved external symbol "public: static int S<char>::a" (?a@?$S@D@@2HA) referenced in function _main
at link time.

Fügen Sie einen Initialisierer hinzu, um das Problem zu beheben:To resolve the issue, add an initializer:

template <typename> struct S {
    static int a;
};

// Add an initializer for the declaration to be a definition.
template <> int S<char>::a{};

int main() {
    return S<char>::a;
}

Präprozessorausgabe behält Zeilenumbrüche beiPreprocessor output preserves newlines

Der experimentelle Präprozessor behält bei der Verwendung von /P oder /E mit /experimental:preprocessor nun Zeilenumbrüche und Leerzeichen bei.The experimental preprocessor now preserves newlines and whitespace when using /P or /E with /experimental:preprocessor. Diese Änderung kann mithilfe von /d1experimental:preprocessor:oldWhitespacedeaktiviert werden.This change can be disabled by using /d1experimental:preprocessor:oldWhitespace.

Gehen wir von folgender Beispielquelle aus:Given this example source,

#define m()
line m(
) line

Die vorherige Ausgabe von /E lautete:The previous output of /E was:

line line
#line 2

Die neue Ausgabe von /E lautet nun:The new output of /E is now:

line
 line

Die Schlüsselwörter „import“ und „module“ sind kontextabhängig'import' and 'module' keywords are context-dependent

Pro P1857R1 gelten für die Präprozessoranweisungen „import“ und „module“ zusätzliche Syntaxeinschränkungen.Per P1857R1, import and module preprocessor directives have additional restrictions on their syntax. Das folgende Beispiel wird nicht mehr kompiliert:This example no longer compiles:

import // Invalid
m;

Es gibt die folgende Fehlermeldung zurück:It produces the following error message:

error C2146: syntax error: missing ';' before identifier 'm'

Behalten Sie den Import auf derselben Zeile:To resolve the issue, keep the import on the same line:

import m; // OK

Entfernen von „std::weak_equality“ und „std::strong_equality“Removal of std::weak_equality and std::strong_equality

Für das Zusammenführen von P1959R0 muss der Compiler Verhalten sowie Verweise auf die Typen std::weak_equality und std::strong_equality entfernen.The merge of P1959R0 requires the compiler to remove behavior and references to the std::weak_equality and std::strong_equality types.

Das folgende Beispiel wird nicht mehr kompiliert:The code in this example no longer compiles:

#include <compare>

struct S {
    std::strong_equality operator<=>(const S&) const = default;
};

void f() {
    nullptr<=>nullptr;
    &f <=> &f;
    &S::operator<=> <=> &S::operator<=>;
}

Das Beispiel führt nun zu folgenden Fehlern:The example now leads to these errors:

error C2039: 'strong_equality': is not a member of 'std'
error C2143: syntax error: missing ';' before '<=>'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C7546: binary operator '<=>': unsupported operand types 'nullptr' and 'nullptr'
error C7546: binary operator '<=>': unsupported operand types 'void (__cdecl *)(void)' and 'void (__cdecl *)(void)'
error C7546: binary operator '<=>': unsupported operand types 'int (__thiscall S::* )(const S &) const' and 'int (__thiscall S::* )(const S &) const'

Aktualisieren Sie den Code, sodass die integrierten relationalen Operatoren bevorzugt und die entfernten Typen ersetzt werden, um das Problem zu beheben:To resolve the issue, update to prefer the built-in relational operators and replace the removed types:

#include <compare>

struct S {
    std::strong_ordering operator<=>(const S&) const = default; // prefer 'std::strong_ordering'
};

void f() {
    nullptr != nullptr; // use pre-existing builtin operator != or ==.
    &f != &f;
    &S::operator<=> != &S::operator<=>;
}

Änderung des TLS-WächtersTLS Guard changes

Bisher wurden threadlokale Variablen in DLLs vor ihrer ersten Verwendung in Threads, die vor dem Laden der DLL vorhanden waren, nicht richtig initialisiert. Anders verhielt es sich mit dem Thread, der die DLL geladen hat.Previously, thread-local variables in DLLs weren't correctly initialized before their first use on threads that existed before the DLL was loaded, other than the thread that loaded the DLL. Dieser Fehler wurde nun behoben.This defect has now been corrected. Threadlokale Variablen in einer solchen DLL werden sofort initialisiert, bevor sie zum ersten Mal in solchen Threads verwendet werden.Thread-local variables in such a DLL are initialized immediately before their first use on such threads.

Dieses neue Verhalten des Tests auf Initialisierung bei Verwendung von threadlokalen Variablen kann mithilfe des Compilerswitchs /Zc:tlsGuards- deaktiviert werden.This new behavior of testing for initialization on uses of thread-local variables may be disabled by using the /Zc:tlsGuards- compiler switch. Eine weitere Möglichkeit ist das Hinzufügen des [[msvc:no_tls_guard]]-Attributs zu bestimmten threadlokalen Variablen.Or, by adding the [[msvc:no_tls_guard]] attribute to particular thread local variables.

Bessere Diagnose des Aufrufs gelöschter FunktionenBetter diagnosis of call to deleted functions

Unser Compiler war bisher weniger einschränkend in Bezug auf Aufrufe gelöschter Funktionen.Our compiler was more permissive about calls to deleted functions previously. Wenn die Aufrufe beispielsweise im Kontext eines Vorlagentexts stattfanden, wurden sie nicht diagnostiziert.For example, if the calls happened in the context of a template body, we wouldn't diagnose the call. Zudem wurde bei mehreren Instanzen von Aufrufen gelöschter Funktionen nur eine Diagnose ausgegeben.Additionally, if there were multiple instances of calls to deleted functions, we would only issue one diagnostic. Nun geben wir für jede dieser Instanzen eine Diagnose aus.Now we issue a diagnostic for each of them.

Eine Konsequenz des neuen Verhaltens kann zu einem kleinen Breaking Change führen: Code, der eine gelöschte Funktion aufgerufen hat, wurde nicht diagnostiziert, wenn er nie für die Codegenerierung benötigt wurde.One consequence of the new behavior can produce a small breaking change: Code that called a deleted function wouldn't get diagnosed if it was never needed for code generation. Nun wird er vorab diagnostiziert.Now we diagnose it up front.

In diesem Beispiel wird Code angezeigt, der nun zu einem Fehler führt:This example shows code that now produces an error:

struct S {
  S() = delete;
  S(int) { }
};

struct U {
  U() = delete;
  U(int i): s{ i } { }

  S s{};
};

U u{ 0 };
error C2280: 'S::S(void)': attempting to reference a deleted function
note: see declaration of 'S::S'
note: 'S::S(void)': function was explicitly deleted

Entfernen Sie Aufrufe gelöschter Funktionen, um das Problem zu beheben:To resolve the issue, remove calls to deleted functions:

struct S {
  S() = delete;
  S(int) { }
};

struct U {
  U() = delete;
  U(int i): s{ i } { }

  S s;  // Do not call the deleted ctor of 'S'.
};

U u{ 0 };

Verbesserungen der Konformität in Visual Studio 2019, Version 16.6Conformance improvements in Visual Studio 2019 version 16.6

Bei Datenströmen der Standardbibliothek werden Einfügungen von nicht korrekt codierten Zeichentypen abgelehntStandard library streams reject insertions of mis-encoded character types

Beim Einfügen von wchar_t in std::ostream sowie von char16_t oder char32_t in std::ostream oder std::wostream wird üblicherweise ein ganzzahliger Wert ausgegeben.Traditionally, inserting a wchar_t into a std::ostream, and inserting char16_t or char32_t into a std::ostream or std::wostream, outputs its integral value. Beim Einfügen von Zeigern in diese Zeichentypen wird der Zeigerwert ausgegeben.Inserting pointers to those character types outputs the pointer value. Für Programmierer sind beide Verhalten nicht intuitiv.Programmers don't find either case intuitive. Vielmehr erwarten sie, dass die Standardbibliothek die auf Zeichen oder NULL endende Zeichenfolge transcodiert und das Ergebnis ausgibt.They often expect the standard library to transcode the character or null-terminated character string instead, and to output the result.

Mit dem C++20-Vorschlag P1423R3 werden gelöschte insertion-Operatorüberladungen im Datenstrom für diese Kombinationen aus Datenstrom und Zeichen- oder Zeichenzeigertypen hinzugefügt.The C++20 proposal P1423R3 adds deleted stream insertion operator overloads for these combinations of stream and character or character pointer types. Bei Verwendung von /std:c++latest haben die Überladungen zur Folge, dass diese Einfügungen nicht korrekt angegeben werden. Das Verhalten entspricht dadurch nicht einem vermutlich unbeabsichtigten Verhalten.Under /std:c++latest, the overloads make these insertions ill-formed, instead of behaving in what is likely an unintended manner. Wird ein solches Element ermittelt, löst der Compiler den Fehler C2280 aus.The compiler raises error C2280 when one is found. Um das alte Verhalten wiederherzustellen, können Sie das escape hatch-Makro _HAS_STREAM_INSERTION_OPERATORS_DELETED_IN_CXX20 als 1 definieren.You can define the "escape hatch" macro _HAS_STREAM_INSERTION_OPERATORS_DELETED_IN_CXX20 to 1 to restore the old behavior. (Der Vorschlag löscht auch insertion-Operatoren in Datenströmen für char8_t .(The proposal also deletes stream insertion operators for char8_t. Unsere Standardbibliothek hat ähnliche Überladungen implementiert, als Unterstützung für char8_t hinzugefügt wurde. Das „falsche“ Verhalten war für char8_t also nie verfügbar.)Our standard library implemented similar overloads when we added char8_t support, so the "wrong" behavior has never been available for char8_t.)

Dieses Beispiel zeigt das Verhalten bei dieser Änderung:This sample shows the behavior with this change:

#include <iostream>
int main() {
    const wchar_t cw = L'x', *pw = L"meow";
    const char16_t c16 = u'x', *p16 = u"meow";
    const char32_t c32 = U'x', *p32 = U"meow";
    std::cout << cw << ' ' << pw << '\n';
    std::cout << c16 << ' ' << p16 << '\n';
    std::cout << c32 << ' ' << p32 << '\n';
    std::wcout << c16 << ' ' << p16 << '\n';
    std::wcout << c32 << ' ' << p32 << '\n';
}

Der Code erzeugt nun folgende Diagnosemeldungen:The code now produces these diagnostic messages:

error C2280: 'std::basic_ostream<char,std::char_traits<char>> &std::<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,wchar_t)': attempting to reference a deleted function
error C2280: 'std::basic_ostream<char,std::char_traits<char>> &std::<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char16_t)': attempting to reference a deleted function
error C2280: 'std::basic_ostream<char,std::char_traits<char>> &std::<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char32_t)': attempting to reference a deleted function
error C2280: 'std::basic_ostream<wchar_t,std::char_traits<wchar_t>> &std::<<<std::char_traits<wchar_t>>(std::basic_ostream<wchar_t,std::char_traits<wchar_t>> &,char16_t)': attempting to reference a deleted function
error C2280: 'std::basic_ostream<wchar_t,std::char_traits<wchar_t>> &std::<<<std::char_traits<wchar_t>>(std::basic_ostream<wchar_t,std::char_traits<wchar_t>> &,char32_t)': attempting to reference a deleted function

Sie können den Effekt des alten Verhaltens in allen Sprachmodi erzielen, indem Sie Zeichentypen in unsigned int bzw. Zeiger-zu-Zeichen-Typen in const void* konvertieren:You can achieve the effect of the old behavior in all language modes by converting character types to unsigned int, or pointer-to-character types to const void*:

#include <iostream>
int main() {
    const wchar_t cw = L'x', *pw = L"meow";
    const char16_t c16 = u'x', *p16 = u"meow";
    const char32_t c32 = U'x', *p32 = U"meow";
    std::cout << (unsigned)cw << ' ' << (const void*)pw << '\n'; // Outputs "120 0052B1C0"
    std::cout << (unsigned)c16 << ' ' << (const void*)p16 << '\n'; // Outputs "120 0052B1CC"
    std::cout << (unsigned)c32 << ' ' << (const void*)p32 << '\n'; // Outputs "120 0052B1D8"
    std::wcout << (unsigned)c16 << ' ' << (const void*)p16 << '\n'; // Outputs "120 0052B1CC"
    std::wcout << (unsigned)c32 << ' ' << (const void*)p32 << '\n'; // Outputs "120 0052B1D8"
}

Änderung des Rückgabetyps von std::pow() für std::complexChanged return type of std::pow() for std::complex

In der Vergangenheit war die MSVC-Implementierung der Aktionsregeln für den Rückgabetyp der Funktionsvorlage std::pow() nicht korrekt.Previously, the MSVC implementation of the promotion rules for the return type of function template std::pow() was incorrect. Beispielsweise wurde von pow(complex<float>, int) früher complex<float> zurückgegeben.For example, previously pow(complex<float>, int) returned complex<float>. Nun wird der richtige Typ complex<double> zurückgegeben.Now it correctly returns complex<double>. Die Korrektur wurde ohne Bedingungen für alle Standardmodi in Visual Studio 2019 Version 16.6 implementiert.The fix has been implemented unconditionally for all standards modes in Visual Studio 2019 version 16.6.

Diese Änderung kann zu Compilerfehlern führen.This change can cause compiler errors. So konnte pow(complex<float>, int) beispielsweise früher mit float multipliziert werden.For example, previously you could multiply pow(complex<float>, int) by a float. Da complex<T> operator* Argumente desselben Typs erwartet, wird mit dem folgenden Beispiel nun der Compilerfehler „C2676: binary '*': 'std::complex<double>' does not define this operator or a conversion to a type acceptable to the predefined operator“ verursacht:Because complex<T> operator* expects arguments of the same type, the following example now emits compiler error C2676: binary '*': 'std::complex<double>' does not define this operator or a conversion to a type acceptable to the predefined operator:

// pow_error.cpp
// compile by using: cl /EHsc /nologo /W4 pow_error.cpp
#include <complex>

int main() {
    std::complex<float> cf(2.0f, 0.0f);
    (void) (std::pow(cf, -1) * 3.0f);
}

Für dieses Problem sind eine Vielzahl von Korrekturen möglich:There are many possible fixes:

  • Ändern Sie den Typ des Multiplikands float in double .Change the type of the float multiplicand to double. Dieses Argument kann direkt in ein complex<double>-Element konvertiert werden, um dem von pow zurückgegebenen Typ zu entsprechen.This argument can be converted directly to a complex<double> to match the type returned by pow.

  • Schränken Sie das Ergebnis von pow auf complex<float> ein, indem Sie complex<float>{pow(ARG, ARG)} angeben.Narrow the result of pow to complex<float> by saying complex<float>{pow(ARG, ARG)}. Anschließend ist eine Multiplikation mit einem float -Wert möglich.Then you can continue to multiply by a float value.

  • Übergeben Sie float anstelle von int an pow.Pass float instead of int to pow. Dieser Vorgang ist möglicherweise langsamer.This operation may be slower.

  • In einigen Fällen können Sie pow vollständig vermeiden.In some cases, you can avoid pow entirely. Beispielsweise kann pow(cf, -1) durch eine Division ersetzt werden.For example, pow(cf, -1) can be replaced by division.

Ab Visual Studio 2019 Version 16.6 implementiert der Compiler einige bereits vorhandene C++-Warnungen für Code, der als C kompiliert wird. Die folgenden Warnungen sind nun auf unterschiedlichen Ebenen aktiviert: C4060, C4061, C4062, C4063, C4064, C4065, C4808 und C4809.Starting in Visual Studio 2019 version 16.6, the compiler implements some preexisting C++ warnings for code compiled as C. The following warnings are now enabled at different levels: C4060, C4061, C4062, C4063, C4064, C4065, C4808, and C4809. Die Warnungen C4065 und C4060 sind in C standardmäßig deaktiviert.Warnings C4065 and C4060 are disabled by default in C.

Sie werden bei fehlenden case -Anweisungen, nicht definierten enum -Elementen und nicht korrekten bool -Schaltern (Schalter mit zu vielen case-Angaben) ausgelöst.The warnings trigger on missing case statements, undefined enum, and bad bool switches (that is, ones that contain too many cases). Zum Beispiel:For example:

#include <stdbool.h>

int main() {
    bool b = true;
    switch (b) {
        case true: break;
        case false: break;
        default: break; // C4809: switch statement has redundant 'default' label;
                        // all possible 'case' labels are given
    }
}

Entfernen Sie den redundanten default -Fall, um dieses Problem zu beheben:To fix this code, remove the redundant default case:

#include <stdbool.h>

int main() {
    bool b = true;
    switch (b) {
        case true: break;
        case false: break;
    }
}

Unbenannte Klassen in typedef-DeklarationenUnnamed classes in typedef declarations

Ab Visual Studio 2019, Version 16.6, wurde das Verhalten von typedef -Deklarationen so beschränkt, dass es P1766R1 entspricht.Starting in Visual Studio 2019 version 16.6, the behavior of typedef declarations has been restricted to conform to P1766R1. Durch dieses Update können unbenannte Klassen innerhalb einer typedef -Deklaration keine anderen Member enthalten als die folgenden:With this update, unnamed classes within a typedef declaration can't have any members other than:

  • nicht statische Datenmembernon-static data members,
  • Memberklassenmember classes,
  • Memberenumerationenmember enumerations,
  • Standardmemberinitialisiererand default member initializers.

Dieselben Einschränkungen gelten rekursiv für alle geschachtelten Klassen.The same restrictions are applied recursively to each nested class. Durch diese Einschränkung soll die Einfachheit von Strukturen mit typedef -Namen zu Bindungszwecken sichergestellt werden.The restriction is meant to ensure the simplicity of structs that have typedef names for linkage purposes. Diese müssen so einfach sein, dass keine Bindungsberechnungen erforderlich sind, bevor der Compiler den typedef -Namen für die Bindung erreicht.They must be simple enough that no linkage calculations are necessary before the compiler gets to the typedef name for linkage.

Diese Änderung wirkt sich auf alle Standardmodi des Compilers aus.This change affects all standards modes of the compiler. Bei der Standardeinstellung ( /std:c++14 ) und den /std:c++17 -Modi gibt der Compiler bei nicht konformem Code die Warnung C5208 aus.In default (/std:c++14) and /std:c++17 modes, the compiler emits warning C5208 for non-conforming code. Wenn /permissive- angegeben wird, gibt der Compiler die Warnung C5208 als Fehler bei Verwendung von /std:c++14 und Fehler C7626 bei Verwendung von /std:c++17 aus.If /permissive- is specified, the compiler emits warning C5208 as an error under /std:c++14 and emits error C7626 under /std:c++17. Der Compiler gibt den Fehler C7626 für nicht konformen Code aus, wenn /std:c++latest angegeben wird.The compiler emits error C7626 for non-conforming code when /std:c++latest is specified.

Das folgende Beispiel zeigt die Konstrukte, die in unbenannten Strukturen nicht länger zulässig sind.The following sample shows the constructs that are no longer allowed in unnamed structs. Abhängig vom angegebenen Standardmodus werden die Fehler oder Warnungen C5208 bzw. C7626 ausgegeben:Depending on the standards mode specified, C5208 or C7626 errors or warnings are emitted:

struct B { };
typedef struct : B { // inheriting from 'B'; ill-formed
    void f(); // ill-formed
    static int i; // ill-formed
    struct U {
        void f(); // nested class has non-data member; ill-formed
    };
    int j = 10; // default member initializer; ill-formed
} S;

Der obige Code kann korrigiert werden, indem Sie der unbenannten Klasse einen Namen zuweisen:The code above can be fixed by giving the unnamed class a name:

struct B { };
typedef struct S_ : B {
    void f();
    static int i;
    struct U {
        void f();
    };
    int j = 10;
} S;

Importieren von Standardargumenten in C++/CLIDefault argument import in C++/CLI

Aufgrund der steigenden Anzahl von APIs mit Standardargumenten in .NET Core wird nun der Import von Standardargumenten in C++/CLI unterstützt.Because of the increasing number of APIs that have default arguments in .NET Core, we now support default argument import in C++/CLI. Durch diese Änderung kann es bei vorhandenem Code, in dem mehrere Überladungen deklariert sind, zu Fehlern kommen, wie im folgenden Beispiel gezeigt:This change can break existing code where multiple overloads are declared, as in this example:

public class R {
    public void Func(string s) {}   // overload 1
    public void Func(string s, string s2 = "") {} // overload 2;
}

Wenn diese Klasse in C++/CLI importiert wird, tritt beim Aufruf einer der Überladungen ein Fehler auf:When this class is imported into C++/CLI, a call to one of the overloads causes an error:

    (gcnew R)->Func("abc"); // error C2668: 'R::Func' ambiguous call to overloaded function

Der Compiler gibt den Fehler C2668 aus, weil beide Überladungen dieser Argumentliste entsprechen.The compiler emits error C2668 because both overloads match this argument list. In der zweiten Überladung wird das zweite Argument vom Standardargument gefüllt.In the second overload, the second argument is filled in by the default argument. Um dieses Problem zu umgehen, können Sie die redundante Überladung (1) löschen.To work around this problem, you can delete the redundant overload (1). Alternativ verwenden Sie die vollständige Argumentliste und geben die Standardargumente explizit an.Or, use the full argument list and explicitly supply the default arguments.

Fehlerbehebungen und Verhaltensänderungen in Visual Studio 2019Bug fixes and behavior changes in Visual Studio 2019

Reinterpret_cast in einer constexpr-FunktionReinterpret_cast in a constexpr function

reinterpret_cast ist in einer constexpr -Funktion nicht zulässig.A reinterpret_cast is illegal in a constexpr function. Der Microsoft-C++-Compiler lehnte reinterpret_cast früher nur bei Verwendung in einem constexpr -Kontext ab.The Microsoft C++ compiler would previously reject reinterpret_cast only if it were used in a constexpr context. In Visual Studio 2019 diagnostiziert der Compiler im Modus für alle Sprachstandards reinterpret_cast ordnungsgemäß in der Definition einer constexpr -Funktion.In Visual Studio 2019, in all language standards modes, the compiler correctly diagnoses a reinterpret_cast in the definition of a constexpr function. Mit dem folgenden Code wird nun „C3615: constexpr function 'f' cannot result in a constant expression“ ausgelöst.The following code now produces C3615: constexpr function 'f' cannot result in a constant expression.

long long i = 0;
constexpr void f() {
    int* a = reinterpret_cast<int*>(i);
}

Entfernen Sie den Modifizierer constexpr aus der Funktionsdeklaration, um den Fehler zu vermeiden.To avoid the error, remove the constexpr modifier from the function declaration.

Richtige Diagnose für den Bereichskonstruktor „basic_string“Correct diagnostics for basic_string range constructor

In Visual Studio 2019 unterdrückt der basic_string-Bereichskonstruktor nicht mehr die Compilerdiagnose mit static_cast .In Visual Studio 2019, the basic_string range constructor no longer suppresses compiler diagnostics with static_cast. Der folgende Code wird in Visual Studio 2017 ohne Warnungen kompiliert, obwohl bei der Konvertierung von wchar_t in char ein Datenverlust auftreten kann, wenn out initialisiert wird:The following code compiles without warnings in Visual Studio 2017, despite the possible loss of data from wchar_t to char when initializing out:

std::wstring ws = /* … */;
std::string out(ws.begin(), ws.end());

Visual Studio 2019 löst ordnungsgemäß die Warnung „C4244: 'argument': conversion from 'wchar_t' to 'const _Elem', possible loss of data“ aus.Visual Studio 2019 correctly raises warning C4244: 'argument': conversion from 'wchar_t' to 'const _Elem', possible loss of data. Sie können std::string wie im folgenden Beispiel initialisieren, um die Warnung zu vermeiden:To avoid the warning, you can initialize the std::string as shown in this example:

std::wstring ws = L"Hello world";
std::string out;
for (wchar_t ch : ws)
{
    out.push_back(static_cast<char>(ch));
}

Fehlerhafte Aufrufe von „+=“ und „-=“ in „/clr“ oder „/ZW“ werden nun ordnungsgemäß erkanntIncorrect calls to += and -= under /clr or /ZW are now correctly detected

Mit Visual Studio 2017 wurde ein Fehler eingeführt, durch den der Compiler Fehler stillschweigend ignoriert hat und keinen Code für ungültige Aufrufe von „+=“ und „-=“ in /clr oder /ZW generiert hat.A bug was introduced in Visual Studio 2017 that caused the compiler to silently ignore errors and generate no code for the invalid calls to += and -= under /clr or /ZW. Der folgende Code wird in Visual Studio 2017 fehlerfrei kompiliert, löst in Visual Studio 2019 jedoch ordnungsgemäß den Fehler „C2845: 'System::String ^': pointer arithmetic not allowed on this type“ aus:The following code compiles without errors in Visual Studio 2017 but in Visual Studio 2019 it correctly raises error C2845: 'System::String ^': pointer arithmetic not allowed on this type:

public enum class E { e };

void f(System::String ^s)
{
    s += E::e; // C2845 in VS2019
}

Verwenden Sie den Operator mit der Methode „ToString()“, um den Fehler in diesem Beispiel zu vermeiden: s += E::e.ToString();.To avoid the error in this example, use the operator with the ToString() method: s += E::e.ToString();.

Initialisierer für statische Inline-DatenmemberInitializers for inline static data members

Ungültige Memberzugriffe innerhalb der Initialisierer inline und static constexpr werden nun ordnungsgemäß erkannt.Invalid member accesses within inline and static constexpr initializers are now correctly detected. Der folgende Beispielcode wird in Visual Studio 2017 fehlerfrei kompiliert, in Visual Studio 2019 wird im /std:c++17 -Modus jedoch der Fehler „C2248: cannot access private member declared in class 'X'“ ausgelöst.The following example compiles without error in Visual Studio 2017, but in Visual Studio 2019 under /std:c++17 mode it raises error C2248: cannot access private member declared in class 'X'.

struct X
{
    private:
        static inline const int c = 1000;
};

struct Y : X
{
    static inline int d = c; // C2248 in Visual Studio 2019
};

Deklarieren Sie den Member X::c als geschützt, um diesen Fehler zu vermeiden:To avoid the error, declare the member X::c as protected:

struct X
{
    protected:
        static inline const int c = 1000;
};

Wiederherstellung der Warnung C4800C4800 reinstated

MSVC verwendete bisher die Leistungswarnung C4800 bei einer impliziten Konvertierung in bool .MSVC used to have a performance warning C4800 about implicit conversion to bool. Sie war zu störend und konnte nicht unterdrückt werden, sodass wir sie in Visual Studio 2017 entfernt haben.It was too noisy and couldn't be suppressed, leading us to remove it in Visual Studio 2017. Allerdings gab es während des Lebenszyklus von Visual Studio 2017 viel Feedback zu den nützlichen Fällen, die dank dieser Warnung behoben werden konnten.However, over the lifecycle of Visual Studio 2017 we got lots of feedback on the useful cases it was solving. Daher haben wir die Warnung C4800 sorgfältig angepasst und bieten sie in Visual Studio 2019 zusammen mit einer erläuternden C4165 wieder an.We bring back in Visual Studio 2019 a carefully tailored C4800, along with the explanatory C4165. Beide Warnungen können problemlos unterdrückt werden: entweder durch eine explizite Umwandlung oder durch den Vergleich mit 0 des entsprechenden Typs.Both of these warnings are easy to suppress: either by using an explicit cast, or by comparison to 0 of the appropriate type. Die Warnung C4800 ist eine standardmäßig deaktivierte Warnung der Stufe 4, und die Warnung C4165 ist eine standardmäßig deaktivierte Warnung der Stufe 3.C4800 is an off-by-default level 4 warning, and C4165 is an off-by-default level 3 warning. Beide können mithilfe der Compileroption /Wall gefunden werden.Both are discoverable by using the /Wall compiler option.

Im folgenden Beispiel werden die Warnungen C4800 und C4165 in /Wall ausgelöst:The following example raises C4800 and C4165 under /Wall:

bool test(IUnknown* p)
{
    bool valid = p; // warning C4800: Implicit conversion from 'IUnknown*' to bool. Possible information loss
    IDispatch* d = nullptr;
    HRESULT hr = p->QueryInterface(__uuidof(IDispatch), reinterpret_cast<void**>(&d));
    return hr; // warning C4165: 'HRESULT' is being converted to 'bool'; are you sure this is what you want?
}

Sie können den Code folgendermaßen schreiben, um die Warnungen im vorherigen Beispiel zu vermeiden:To avoid the warnings in the previous example, you can write the code like this:

bool test(IUnknown* p)
{
    bool valid = p != nullptr; // OK
    IDispatch* d = nullptr;
    HRESULT hr = p->QueryInterface(__uuidof(IDispatch), reinterpret_cast<void**>(&d));
    return SUCCEEDED(hr);  // OK
}

Lokale Klassenmemberfunktion enthält keinen TextLocal class member function doesn't have a body

In Visual Studio 2017 wird die Warnung „C4822: Local class member function doesn't have a body“ nur ausgelöst, wenn die Compileroption /w14822 explizit festgelegt ist.In Visual Studio 2017, warning C4822: Local class member function doesn't have a body is raised only when compiler option /w14822 is explicitly set. Bei Verwendung von /Wall wird sie nicht angezeigt.It isn't shown with /Wall. In Visual Studio 2019 ist die Warnung C4822 standardmäßig deaktiviert und in /Wall auffindbar, ohne dass /w14822 explizit festgelegt sein muss.In Visual Studio 2019, C4822 is an off-by-default warning, which makes it discoverable under /Wall without having to set /w14822 explicitly.

void example()
{
    struct A
        {
            int boo(); // warning C4822
        };
}

Funktionsvorlagentexte, die if constexpr-Anweisungen enthaltenFunction template bodies containing constexpr if statements

Für Funktionsvorlagentexte, die if constexpr-Anweisungen enthalten, sind einige auf die Analyse bezogene /permissive--Überprüfungen aktiviert.Template function bodies containing if constexpr statements have some /permissive- parsing-related checks enabled. Der folgende Code löst in Visual Studio 2017 z. B. nur dann „C7510: 'Type': use of dependent type name must be prefixed with 'typename'“ aus, wenn die Option /permissive- nicht festgelegt ist.For example, in Visual Studio 2017 the following code produces C7510: 'Type': use of dependent type name must be prefixed with 'typename' only if the /permissive- option isn't set. Der gleiche Code löst in Visual Studio 2019 selbst dann Fehler aus, wenn die Option /permissive- festgelegt ist:In Visual Studio 2019 the same code raises errors even when the /permissive- option is set:

template <typename T>

int f()
{
    T::Type a; // error C7510

    if constexpr (T::val)
    {
        return 1;
    }
    else
    {
        return 2;
    }
}

struct X
{
    using Type = X;
    constexpr static int val = 1;
};

int main()
{
    return f<X>();
}

Fügen Sie das Schlüsselwort typename zur Deklaration von a hinzu, um den Fehler zu vermeiden: typename T::Type a;.To avoid the error, add the typename keyword to the declaration of a: typename T::Type a;.

Inlineassemblycode wird in Lambdaausdrücken nicht unterstütztInline assembly code isn't supported in a lambda expression

Das Microsoft C++-Team wurde vor Kurzem auf ein Sicherheitsproblem hingewiesen, durch das die Verwendung von Inlineassemblern innerhalb eines Lambdaausdrucks bei der Ausführung zur Beschädigung von ebp (das Register für Rückgabeadressen) führen kann.The Microsoft C++ team was recently made aware of a security issue in which the use of inline-assembler within a lambda could lead to the corruption of ebp (the return address register) at runtime. Ein böswilliger Angreifer könnte sich dieses Szenario zunutze machen.A malicious attacker could possibly take advantage of this scenario. Der Inlineassembler wird nur bei x86 unterstützt, und zwischen dem Inlineassembler und den übrigen Elementen des Compilers findet keine zufriedenstellende Interaktion statt.The inline assembler is only supported on x86, and interaction between the inline assembler and the rest of the compiler is poor. Aufgrund dieser Tatsachen und der Art des Problems bestand die sicherste Lösung darin, den Inlineassembler innerhalb eines Lambdaausdrucks nicht zuzulassen.Given these facts and the nature of the issue, the safest solution to this problem was to disallow inline assembler within a lambda expression.

Die einzige Verwendung eines Inlineassemblers innerhalb eines Lambdaausdrucks, die in der Praxis gefunden wurde, war das Erfassen der Rückgabeadresse.The only use of inline assembler within a lambda expression that we have found 'in the wild' was to capture the return address. In diesem Szenario können Sie die Rückgabeadresse auf allen Plattformen erfassen, indem Sie einfach die intrinsische Compilerfunktion _ReturnAddress() verwenden.In this scenario, you can capture the return address on all platforms simply by using a compiler intrinsic _ReturnAddress().

Der folgende Code erzeugt sowohl in Visual Studio 2017 15.9 als auch in Visual Studio 2019 den Fehler „C7552: inline assembler is not supported in a lambda“:The following code produces C7552: inline assembler is not supported in a lambda in both Visual Studio 2017 15.9 and in Visual Studio 2019:

#include <cstdio>

int f()
{
    int y = 1724;
    int x = 0xdeadbeef;

    auto lambda = [&]
    {
        __asm {

            mov eax, x
            mov y, eax
        }
    };

    lambda();
    return y;
}

Verschieben Sie den Assemblycode wie im folgenden Beispiel gezeigt in eine benannte Funktion, um diesen Fehler zu vermeiden:To avoid the error, move the assembly code into a named function as shown in the following example:

#include <cstdio>

void g(int& x, int& y)
{
    __asm {
        mov eax, x
        mov y, eax
    }
}

int f()
{
    int y = 1724;
    int x = 0xdeadbeef;
    auto lambda = [&]
    {
        g(x, y);
    };
    lambda();
    return y;
}

int main()
{
    std::printf("%d\n", f());
}

Iteratordebuggen und std::move_iteratorIterator debugging and std::move_iterator

Das Feature für das Iteratordebuggen kann std::move_iterator nun ordnungsgemäß entpacken.The iterator debugging feature has been taught to properly unwrap std::move_iterator. Beispielsweise kann std::copy(std::move_iterator<std::vector<int>::iterator>, std::move_iterator<std::vector<int>::iterator>, int*) nun den schnellen Pfad memcpy binden.For example, std::copy(std::move_iterator<std::vector<int>::iterator>, std::move_iterator<std::vector<int>::iterator>, int*) can now engage the memcpy fast path.

Fehlerbehebung der Schlüsselworterzwingung <xkeycheck.h>Fixes for <xkeycheck.h> keyword enforcement

Die makro-ersetzende Schlüsselworterzwingung <xkeycheck.h> der Standardbibliothek wurde behoben, sodass nun das tatsächliche Schlüsselwort ermittelt wird, anstelle einer generischen Meldung.The standard library's macro replacing a keyword enforcement <xkeycheck.h> was fixed to emit the actual problem keyword detected rather than a generic message. C++20-Schlüsselwörter werden ebenfalls unterstützt, und es wird vermieden, dass IntelliSense zufällige Schlüsselwörter als Makros erkennt.It also supports C++20 keywords, and avoids tricking IntelliSense into saying random keywords are macros.

Zuweisungstypen sind nicht mehr als veraltet markiert.Allocator types no longer deprecated

std::allocator<void>, std::allocator::size_type und std::allocator::difference_type sind nicht mehr als veraltet markiert.std::allocator<void>, std::allocator::size_type, and std::allocator::difference_type are no longer deprecated.

Richtige Warnungen für einschränkende ZeichenfolgenkonvertierungenCorrect warning for narrowing string conversions

Ein nicht beabsichtigter static_cast von std::string, der für den Standard nicht erforderlich ist und versehentlich C4244-Warnungen unterdrückt hat, wurde entfernt.Removed a spurious static_cast from std::string that wasn't called for by the standard, and that accidentally suppressed C4244 narrowing warnings. Beim Versuch, std::string::string(const wchar_t*, const wchar_t*) aufzurufen, wird nun ordnungsgemäß die Warnung „C4244 narrowing a wchar_t into a char“ ausgelöst.Attempts to call std::string::string(const wchar_t*, const wchar_t*) now properly emit C4244 narrowing a wchar_t into a char.

Unterschiedliche <filesystem>-Korrekturen der GenauigkeitVarious <filesystem> correctness fixes

  • Das Fehlschlagen von std::filesystem::last_write_time beim Versuch, den letzten Schreibzugriff eines Verzeichnisses zu ändern, wurde behoben.Fixed std::filesystem::last_write_time failing when attempting to change a directory's last write time.
  • Der Konstruktor std::filesystem::directory_entry speichert nun ein fehlgeschlagenes Ergebnis, anstatt eine Ausnahme auszulösen, wenn ein nicht vorhandener Zielpfad angegeben wird.The std::filesystem::directory_entry constructor now stores a failed result, rather than throwing an exception, when supplied a nonexistent target path.
  • Die Version von std::filesystem::create_directory mit zwei Parametern wurde geändert, sodass nun die Version mit einem Parameter aufgerufen wird, da die zugrundeliegende CreateDirectoryExW-Funktion copy_symlink verwenden würde, wenn existing_p eine symbolische Verknüpfung ist.The std::filesystem::create_directory 2-parameter version was changed to call the 1-parameter version, as the underlying CreateDirectoryExW function would use copy_symlink when the existing_p was a symlink.
  • std::filesystem::directory_iterator schlägt nicht mehr fehl, wenn eine fehlerhafte symbolische Verknüpfung festgestellt wird.std::filesystem::directory_iterator no longer fails when a broken symlink is found.
  • std::filesystem::space akzeptiert jetzt relative Pfade.std::filesystem::space now accepts relative paths.
  • std::filesystem::path::lexically_relative wird nicht mehr durch nachstehende Schrägstriche behindert (siehe LWG 3096).std::filesystem::path::lexically_relative is no longer confused by trailing slashes, reported as LWG 3096.
  • Das Ablehnen von Pfaden mit umgekehrten Schrägstrichen von CreateSymbolicLinkW in std::filesystem::create_symlink wurde behoben.Worked around CreateSymbolicLinkW rejecting paths with forward slashes in std::filesystem::create_symlink.
  • Es wurde ein Problem behoben, bei dem die delete-Funktion des POSIX-Löschmodus unter Windows 10 LTSB 1609 zwar vorhanden war, aber keine Dateien löschen konnte.Worked around the POSIX deletion mode delete function that existed in Windows 10 LTSB 1609, but couldn't actually delete files.
  • Die Kopierkonstruktoren und Kopierzuweisungsoperatoren von std::boyer_moore_searcher und std::boyer_moore_horspool_searcher sind nun in der Lage, Kopiervorgänge tatsächlich durchzuführen.std::boyer_moore_searcher and std::boyer_moore_horspool_searcher's copy constructors and copy assignment operators now actually copy things.

Parallele Algorithmen unter Windows 8 und höherParallel algorithms on Windows 8 and later

Die Bibliothek mit parallelen Algorithmen verwendet unter Windows 8 und höher nun ordnungsgemäß die echte WaitOnAddress-Familie, anstatt immer die gefälschten Versionen von Windows 7 und früher zu verwenden.The parallel algorithms library now properly uses the real WaitOnAddress family on Windows 8 and later, rather than always using the Windows 7 and earlier fake versions.

std::system_category::message() Leerzeichenstd::system_category::message() whitespace

std::system_category::message() schneidet nachstehenden Leerraum von der zurückgegebenen Meldung nun ab.std::system_category::message() now trims trailing whitespace from the returned message.

std::linear_congruential_engine Division durch 0std::linear_congruential_engine divide by zero

Einige Bedingungen wurden behoben, die dazu führten, dass std::linear_congruential_engine eine Division durch 0 (null) durchführte.Some conditions that would cause std::linear_congruential_engine to trigger divide by 0 have been fixed.

Fehlerbehebungen für das Entpacken von IteratorenFixes for iterator unwrapping

In Visual Studio 2017 Version 15.8 wurde erstmalig eine Funktion zum Entpacken von Iteratoren für Programmierer zur Verfügung gestellt, wie im C++-Teamblogartikel STL Features and Fixes in VS 2017 15.8 (STL-Funktionen und Fehlerbehebungen in VS 2017 15.8) beschrieben.Some iterator-unwrapping machinery was first exposed for programmer-user integration in Visual Studio 2017 15.8, as described in C++ Team Blog article STL Features and Fixes in VS 2017 15.8. Mit dieser Funktion werden Iteratoren, die von Standardbibliotheksiteratoren abgeleitet wurden, nicht mehr entpackt.This machinery no longer unwraps iterators derived from standard library iterators. Ein Benutzer, der beispielsweise von std::vector<int>::iterator abgeleitet wird und versucht, das Verhalten anzupassen, erhält nun das angepasste Verhalten, wenn er Algorithmen der Standardbibliothek aufruft, anstelle des Verhaltens eines Zeigers.For example, a user that derives from std::vector<int>::iterator and tries to customize behavior now gets their customized behavior when calling standard library algorithms, rather than the behavior of a pointer.

Die reserve-Funktion für ungeordnete Container reserviert N-Elemente nun tatsächlich (siehe LWG 2156).The unordered container reserve function now actually reserves for N elements, as described in LWG 2156.

Behandlung von ZeitTime handling

  • Zuvor führten einige Zeitwerte, die an die Parallelitätsbibliothek übergeben wurden, zu einem Überlauf, z. B. condition_variable::wait_for(seconds::max()).Previously, some time values that were passed to the concurrency library would overflow, for example, condition_variable::wait_for(seconds::max()). Diese mittlerweile behobenen Überläufe haben das Verhalten in einem scheinbar willkürlichen 29-tägigen Zyklus geändert (wenn von den zugrundeliegenden Win32-APIs akzeptierte uint32_t Millisekunden zu einem Überlauf führten).Now fixed, the overflows changed behavior on a seemingly random 29-day cycle (when uint32_t milliseconds accepted by underlying Win32 APIs overflowed).

  • Der <ctime>-Header deklariert timespec und timespec_get im Namespace std jetzt ordnungsgemäß und im globalen Namespace.The <ctime> header now correctly declares timespec and timespec_get in namespace std, in addition to declaring them in the global namespace.

Verschiedene Fehlerbehebungen für ContainerVarious fixes for containers

  • Viele interne Containerfunktionen der Standardbibliothek sind nun privat, um die Funktionsweise von IntelliSense zu verbessern.Many standard library internal container functions have been made private for an improved IntelliSense experience. In zukünftigen Releases von MSVC sind weitere Fehlerbehebungen zu erwarten, die Member als privat kennzeichnen.Additional fixes to mark members as private are expected in later releases of MSVC.

  • Probleme bei der Richtigkeit der Ausnahmesicherheit, durch die knotenbasierte Container wie list, map und unordered_map beschädigt wurden, wurden behoben.Exception safety correctness problems wherein the node-based containers like list, map, and unordered_map would become corrupted were fixed. Während einem propagate_on_container_copy_assignment- oder propagate_on_container_move_assignment-Neuzuweisungsvorgang würden Sie den Sentinelknoten des Containers mit der alten Zuweisung freistellen, die alte Zuweisung mit der POCCA/POCMA-Zuweisung überschreiben und dann versuchen, den Sentinelknoten der neuen Zuweisung abzurufen.During a propagate_on_container_copy_assignment or propagate_on_container_move_assignment reassignment operation, we would free the container's sentinel node with the old allocator, do the POCCA/POCMA assignment over the old allocator, and then try to acquire the sentinel node from the new allocator. Wenn bei dieser Zuweisung ein Fehler auftritt, ist der Container beschädigt und kann nicht einmal zerstört werden, da der Besitz eines Sentinelknotens eine feste Datenstrukturinvariante darstellt.If this allocation failed, the container was corrupted and couldn't even be destroyed, as owning a sentinel node is a hard data structure invariant. Dieser Code wurde korrigiert, sodass der neue Sentinelknoten der Zuweisung des Quellcontainers zugewiesen wird, bevor der vorhandene Sentinelknoten zerstört wird.This code was fixed to allocate the new sentinel node from the source container's allocator before destroying the existing sentinel node.

  • Die Container wurden behoben, sodass sie Zuweisungen immer in propagate_on_container_copy_assignment, propagate_on_container_move_assignment und propagate_on_container_swap kopieren/verschieben/tauschen. Dies gilt auch für Zuweisungen mit einer Deklaration von is_always_equal.The containers were fixed to always copy/move/swap allocators according to propagate_on_container_copy_assignment, propagate_on_container_move_assignment, and propagate_on_container_swap, even for allocators declared is_always_equal.

  • Es wurden Überladungen für Funktionen zum Zusammenführen von Containern und Extrahieren von Membern hinzugefügt, die rvalue-Container gemäß P0083 "Splicing Maps And Sets" (Splice-Zuordnungen und -Sätze) akzeptierenAdded the overloads for container merge and extract member functions that accept rvalue containers, per P0083 "Splicing Maps And Sets"

std::basic_istream::read-Verarbeitung von \r\n => \nstd::basic_istream::read processing of \r\n => \n

std::basic_istream::read wurde behoben, sodass bei der Verarbeitung von \r\n => \n nicht temporär in den angegebenen Puffer geschrieben wird.std::basic_istream::read was fixed to not write into parts of the supplied buffer temporarily as part of \r\n => \n processing. Durch diese Änderung entfällt ein Teil des Leistungsvorteils, der in Visual Studio 2017 15.8 für Lesezugriffe größer als 4K erzielt wurde.This change gives up some of the performance advantage that was gained in Visual Studio 2017 15.8 for reads larger than 4K in size. Es gibt jedoch weiterhin Effizienzsteigerungen durch die Vermeidung von drei virtuellen Aufrufen pro Zeichen.However, efficiency improvements from avoiding three virtual calls per character are still present.

std::bitset-Konstruktorstd::bitset constructor

Der Konstruktor von std::bitset liest die Einsen und Nullen von großen Bitsets nicht mehr in umgekehrter Reihenfolge.The std::bitset constructor no longer reads the ones and zeroes in reverse order for large bitsets.

std::pair::operator=-Regressionstd::pair::operator= regression

Eine Regression im Zuweisungsoperator von std::pair wurde behoben, die bei der Implementierung von LWG 2729 "Missing SFINAE on std::pair::operator="; (SFINAE für std::pair::operator= fehlt) eingeführt wurde.Fixed a regression in std::pair's assignment operator introduced when implementing LWG 2729 "Missing SFINAE on std::pair::operator=";. Typen, die in std::pair konvertiert werden können, werden nun wieder ordnungsgemäß akzeptiert.It now correctly accepts types convertible to std::pair again.

Nicht abgeleitete Kontexte für add_const_tNon-deduced contexts for add_const_t

Ein kleiner Fehler bei Typmerkmalen wurde behoben, bei dem add_const_t und zugehörige Funktionen einem nicht abgeleiteten Kontext entsprechen sollten.Fixed a minor type traits bug, where add_const_t and related functions are supposed to be a non-deduced context. Das heißt, add_const_t sollte ein Alias für typename add_const<T>::type sein, nicht für const T.In other words, add_const_t should be an alias for typename add_const<T>::type, not const T.

Fehlerbehebungen und Verhaltensänderungen in 16.2Bug fixes and behavior changes in 16.2

Const-Vergleichsoperatoren für assoziative ContainerConst comparators for associative containers

Der Code für die Suche und das Einfügen in Menge, Zuordnung, Multimenge, und Mehrfachzuordnung wurde zusammengeführt, um die Codegröße zu reduzieren.Code for search and insertion in set, map, multiset, and multimap has been merged for reduced code size. Auf die gleiche Weise wie früher bei Suchvorgängen rufen Einfügevorgänge nun den „Kleiner als“-Vergleich in einem const -Vergleichsfunktor auf.Insertion operations now call the less-than comparison on a const comparison functor, in the same way that search operations have done previously. Der folgende Code wird in Visual Studio 2019 Version 16.1 und früher kompiliert, erzeugt jedoch C3848 in Visual Studio 2019 Version 16.2:The following code compiles in Visual Studio 2019 version 16.1 and earlier, but raises C3848 in Visual Studio 2019 version 16.2:

#include <iostream>
#include <map>

using namespace std;

struct K
{
   int a;
   string b = "label";
};

struct Comparer  {
   bool operator() (K a, K b) {
      return a.a < b.a;
   }
};

map<K, double, Comparer> m;

K const s1{1};
K const s2{2};
K const s3{3};

int main() {

   m.emplace(s1, 1.08);
   m.emplace(s2, 3.14);
   m.emplace(s3, 5.21);

}

Legen Sie den Vergleichsoperator als const fest, um den Fehler zu vermeiden:To avoid the error, make the comparison operator const:

struct Comparer  {
   bool operator() (K a, K b) const {
      return a.a < b.a;
   }
};

Verbesserungen der Konformität in Visual Studio 2017 RTW (Version 15.0)Conformance improvements in Visual Studio 2017 RTW (version 15.0)

Mit der Unterstützung für generalisierte constexpr -Elemente und der Initialisierung für nicht statische Datenelemente (Non-Static Data Member Initialization, NSDMI) für Aggregate ist der Microsoft-C++-Compiler in Visual Studio 2017 für Features, die im C++14-Standard hinzugefügt wurden, jetzt vollständig.With support for generalized constexpr and non-static data member initialization (NSDMI) for aggregates, the Microsoft C++ compiler in Visual Studio 2017 is now complete for features added in the C++14 standard. Dem Compiler fehlen jedoch noch einige Funktionen der C++11- und C++98-Standards.However, the compiler still lacks a few features from the C++11 and C++98 standards. Eine Tabelle mit dem aktuellen Compilerstatus finden Sie unter Microsoft C++-Sprachkonformität: Tabelle.See Microsoft C++ language conformance table for a table that shows the current state of the compiler.

C++11: Unterstützung für SFINAE für Ausdrücke in mehr BibliothekenC++11: Expression SFINAE support in more libraries

Die Unterstützung für den SFINAE-Ausdruck wird im Compiler weiterhin verbessert.The compiler continues to improve its support for expression SFINAE. Dies ist für die Vorlagenargumentableitung und -ersetzung erforderlich, bei der die Ausdrücke decltype und constexpr möglicherweise als Vorlagenparameter angezeigt werden.It's required for template argument deduction and substitution where decltype and constexpr expressions may appear as template parameters. Weitere Informationen finden Sie unter Expression SFINAE improvements in Visual Studio 2017 RC (Verbesserungen der SFINAE für Ausdrücke in Visual Studio 2017).For more information, see Expression SFINAE improvements in Visual Studio 2017 RC.

C++14: NSDMI für AggregateC++14: NSDMI for Aggregates

Ein Aggregat ist ein Array oder eine Klasse ohne einen vom Benutzer bereitgestellten Konstruktor, ohne private oder geschützte nicht statische Datenmember, ohne Basisklassen und ohne virtuelle Funktionen.An aggregate is an array or a class that has no user-provided constructor, no private or protected non-static data members, no base classes, and no virtual functions. Ab C++14 können Aggregate Memberinitialisierer enthalten.Beginning in C++14, aggregates may contain member initializers. Weitere Informationen finden Sie unter Member initializers and aggregates (Memberinitialisierer und Aggregate).For more information, see Member initializers and aggregates.

C++14: Erweiterte constexprC++14: Extended constexpr

Als constexpr deklarierte Ausdrücke dürfen jetzt bestimmte Arten von Deklarationen, if- und switch-Anweisungen, Schleifenanweisungen und Mutationen von Objekten enthalten, deren Lebensdauer in der Auswertung von constexpr-Ausdrücken begonnen hat.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. Darüber hinaus ist es nicht mehr erforderlich, dass eine nicht statische Memberfunktion von constexpr implizit const ist.There's no longer a requirement that a constexpr non-static member function must be implicitly const. Weitere Informationen finden Sie unter Relaxing constraints on constexpr functions (Lockerung der Einschränkungen auf constexpr-Funktionen).For more information, see Relaxing constraints on constexpr functions.

C++17: Nicht ausführliche static_assertC++17: Terse static_assert

Der Meldungsparameter für static_assert ist optional.the message parameter for static_assert is optional. Weitere Informationen finden Sie unter Extending static_assert, v2 (Erweitern des static_assert, v2).For more information, see Extending static_assert, v2.

C++17: [[fallthrough]]-AttributC++17: [[fallthrough]] attribute

Im /std:c++17 -Modus kann das [[fallthrough]]-Attribut im Kontext von switch-Anweisungen als Hinweis für den Compiler verwendet werden, dass das Fall-Through-Verhalten vorgesehen ist.In /std:c++17 mode, 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. Dieses Attribut verhindert, dass der Compiler in solchen Fällen Warnungen ausgeben kann.This attribute prevents the compiler from issuing warnings in such cases. Weitere Informationen finden Sie unter Wording for [[fallthrough]] attribute (Worlaut für [[fallthrough]]-Attribut).For more information, see Wording for [[fallthrough]] attribute.

Verallgemeinerte bereichsbasierte for-SchleifenGeneralized range-based for loops

Bereichsbezogene for-Schleifen erfordern nicht mehr, dass begin() und end() Objekte des gleichen Typs zurückgeben.Range-based for loops no longer require that begin() and end() return objects of the same type. Diese Änderung ermöglicht end() die Rückgabe eines Sentinels wie von Bereichen in range-v3 verwendet und die Einhaltung der abgeschlossenen, jedoch noch nicht ganz veröffentlichten technische Spezifikation zu Bereichen.This change enables end() to return a sentinel as used by ranges in range-v3 and the completed-but-not-quite-published Ranges Technical Specification. Weitere Informationen finden Sie unter Generalizing the Range-Based For Loop (Generalisieren einer bereichsbasierten for-Schleife).For more information, see Generalizing the Range-Based For Loop.

Verbesserungen der Konformität in 15.3Conformance improvements in 15.3

constexpr-Lambdasconstexpr lambdas

Lambdaausdrücke können jetzt in konstanten Ausdrücken verwendet werden.Lambda expressions may now be used in constant expressions. Weitere Informationen finden Sie unter constexpr-Lambdaausdrücke in C++.For more information, see constexpr lambda expressions in C++.

if constexpr in Funktionsvorlagenif constexpr in function templates

Eine Funktionsvorlage kann if constexpr -Anweisungen enthalten, um das Branchen zur Kompilierzeit zu unterstützen.A function template may contain if constexpr statements to enable compile-time branching. Weitere Informationen finden Sie unter if constexpr-Anweisungen.For more information, see if constexpr statements.

Auswahlanweisungen mit InitialisierernSelection statements with initializers

Eine if -Anweisung kann einen Initialisierer enthalten, der innerhalb der Anweisung selbst im Blockbereich eine Variable einführt.An if statement may include an initializer that introduces a variable at block scope within the statement itself. Weitere Informationen finden Sie unter if-Anweisungen mit Initialisierer.For more information, see if statements with initializer.

[[maybe_unused]]- und [[nodiscard]]-Attribute[[maybe_unused]] and [[nodiscard]] attributes

Ein neues [[maybe_unused]]-Attribut schaltet Warnungen aus, wenn eine Entität nicht verwendet wird.New attribute [[maybe_unused]] silences warnings when an entity isn't used. Das [[nodiscard]]-Attribut generiert eine Warnung, wenn der Rückgabewert eines Funktionsaufrufs verworfen wird.The [[nodiscard]] attribute creates a warning if the return value of a function call is discarded. Weitere Informationen finden Sie unter Attribute in C++.For more information, see Attributes in C++.

Verwenden von Attributnamespaces ohne WiederholungUsing attribute namespaces without repetition

Neue Syntax, um nur einen einzigen Namespacebezeichner in einer Attributliste zu erlauben.New syntax to enable only a single namespace identifier in an attribute list. Weitere Informationen finden Sie unter Attribute in C++.For more information, see Attributes in C++.

Strukturierte BindungenStructured bindings

Es ist jetzt möglich, einen Wert mit individuellen Namen für die verschiedenen Komponenten in einer einzigen Anweisung zu speichern. Dies gilt, wenn der Wert ein Array, std::tuple oder std::pair ist oder nur öffentliche, nicht statische Datenmember enthält.It's 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. Weitere Informationen finden Sie unter Structured Bindings (Strukturierte Bindungen) und Returning multiple values from a function (Zurückgeben von mehreren Werten aus einer Funktion).For more information, see Structured Bindings and Returning multiple values from a function.

Erstellungsregeln für enum class-KlassenwerteConstruction rules for enum class values

Für den zugrunde liegenden Typ einer Enumeration mit eigenem Gültigkeitsbereich wird jetzt eine implizite und nicht einschränkende Konvertierung in die Enumeration selbst durchgeführt.There's now an implicit and non-narrowing conversion from a scoped enumeration's underlying type to the enumeration itself. Diese Konvertierung ist verfügbar, wenn in der Definition kein Enumerator eingeführt wird und in der Quelle eine Listeninitialisierungsyntax verwendet wird.The conversion is available when its definition doesn't introduce an enumerator, and when the source uses a list-initialization syntax. Weitere Informationen finden Sie unter Construction Rules for enum class Values (Erstellungsregeln für enum-Klassenwerte) und Enumerations (Enumerationen).For more information, see Construction Rules for enum class Values and Enumerations.

Erfassen von *this nach WertCapturing *this by value

Das *this -Objekt in einem Lambdaausdruck kann jetzt anhand des Werts erfasst werden.The *this object in a lambda expression may now be captured by value. Diese Änderung ermöglicht Szenarios in denen der Lambdaausdruck in parallelen und asynchronen Vorgängen aufgerufen wird, insbesondere in neueren Computerarchitekturen.This change enables scenarios in which the lambda is invoked in parallel and asynchronous operations, especially on newer machine architectures. Weitere Informationen finden Sie unter LLambda Capture of *this by Value as [=,*this] (Lambdaerfassung von „*this“ anhand des Werts als =,this).For more information, see Lambda Capture of *this by Value as [=,*this].

Entfernen von operator++ für boolRemoving operator++ for bool

operator++ wird für bool -Typen nicht mehr unterstützt.operator++ is no longer supported on bool types. Weitere Informationen finden Sie unter Remove Deprecated operator++(bool) (Veralteten „operator++(bool)“ entfernen).For more information, see Remove Deprecated operator++(bool).

Entfernen des veralteten Schlüsselworts registerRemoving deprecated register keyword

Das Schlüsselwort register , das als veraltet gekennzeichnet und vom Compiler ignoriert wurde, wurde jetzt aus der Sprache entfernt.The register keyword, previously deprecated (and ignored by the compiler), is now removed from the language. Weitere Informationen finden Sie unter Remove Deprecated Use of the registerKeyword (Entfernen der Verwendung des veralteten Schlüsselworts „register“).For more information, see Remove Deprecated Use of the register Keyword.

Verbesserungen der Konformität in 15.5Conformance improvements in 15.5

Funktionen, die mit [14] markiert sind, stehen selbst im /std:c++14 -Modus ohne Bedingungen zur Verfügung.Features marked with [14] are available unconditionally even in /std:c++14 mode.

Neue Compilerschalter für extern constexprNew compiler switch for extern constexpr

In früheren Versionen von Visual Studio hat der Compiler immer eine interne constexpr -Variablenbindung ausgegeben, selbst wenn die Variable als extern markiert wurde.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 Version 15.5 ermöglicht ein neuer Compilerschalter (/Zc:externConstexpr) das richtige standardkonforme Verhalten.In Visual Studio 2017 version 15.5, a new compiler switch, /Zc:externConstexpr, enables correct and standards-conforming behavior. Weitere Informationen finden Sie unter Externe constexpr-Verknüpfung.For more information, see extern constexpr linkage.

Entfernen dynamischer AusnahmespezifikationenRemoving dynamic exception specifications

P0003R5 Dynamische Ausnahmespezifikationen sind in C++11 veraltet.P0003R5 Dynamic exception specifications were deprecated in C++11. Das Feature wird aus C ++ 17 entfernt, aber die (immer noch) veraltete throw()-Spezifikation wird strikt als Alias für noexcept(true) beibehalten.the feature is removed from C++17, but the (still) deprecated throw() specification is kept strictly as an alias for noexcept(true). Weitere Informationen dazu finden Sie unter Entfernen der dynamischen Ausnahmespezifikation und noexcept.For more information, see Dynamic exception specification removal and noexcept.

not_fn()

P0005R4 not_fn ersetzt not1 und not2.P0005R4 not_fn is a replacement of not1 and not2.

Umformulieren von enable_shared_from_thisRewording enable_shared_from_this

P0033R1 enable_shared_from_this wurde in C++11 hinzugefügt.P0033R1 enable_shared_from_this was added in C++11. Der C++17-Standard aktualisiert die Spezifikation, um bestimmte Ausnahmefälle besser zu verarbeiten.The C++17 standard updates the specification to better handle certain corner cases. [14][14]

Splice-Zuordnungen und -SätzeSplicing maps and sets

P0083R3 Dieses Feature ermöglicht das Extrahieren von Knoten aus assoziativen Containern (z.B. map, set, unordered_map, unordered_set), die dann geändert und wieder in den gleichen Container oder einen anderen Container eingefügt werden können, der den gleichen Knotentyp verwendet.P0083R3 This feature enables extraction of nodes from associative containers (that is, 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. (Ein häufiger Anwendungsfall besteht darin, einen Knoten aus einer std::map zu extrahieren, den Schlüssel zu ändern und ihn dann erneut einzufügen.)(A common use case is to extract a node from a std::map, change the key, and reinsert.)

Veraltete rudimentäre BibliotheksteileDeprecating vestigial library parts

P0174R2 Einige Features der C++-Standardbibliothek wurden im Laufe der Jahre durch neuere Features ersetzt, oder es hat sich herausgestellt, dass sie nicht sehr nützlich oder sogar problematisch sind.P0174R2 Several features of the C++ standard library have been superseded by newer features over the years, or else have been found not useful, or problematic. Diese Funktionen werden sind in C++17 offiziell als veraltet eingestuft.These features are officially deprecated in C++17.

Entfernen der Zuweisungsunterstützung in std::functionRemoving allocator support in std::function

P0302R1 Vor C++17 besaß die Klassenvorlage std::function mehrere Konstruktoren, die ein Zuweisungsargument angenommen haben.P0302R1 Prior to C++17, the class template std::function had several constructors that took an allocator argument. Allerdings war die Verwendung von Zuweisungen in diesem Kontext problematisch, und die Semantik war unklar.However, the use of allocators in this context was problematic, and the semantics were unclear. Die problematischen Konstruktoren wurden entfernt.The problem contructors have been removed.

Korrekturen für not_fn()Fixes for not_fn()

P0358R1 Neue Formulierungen für std::not_fn bieten Unterstützung für die Weitergabe der Wertkategorie bei einem Wrapperaufruf.P0358R1 New wording for std::not_fn provides support of propagation of value category when used in wrapper invocation.

shared_ptr<T[]>, shared_ptr<T[N]>shared_ptr<T[]>, shared_ptr<T[N]>

P0414R2 Zusammenführen von shared_ptr-Änderungen aus Library Fundamentals in C++17.P0414R2 Merging shared_ptr changes from Library Fundamentals to C++17. [14][14]

Korrigieren von shared_ptr für ArraysFixing shared_ptr for arrays

P0497R0 Korrekturen an der shared_ptr-Unterstützung für Arrays.P0497R0 Fixes to shared_ptr support for arrays. [14][14]

Erklärung zu insert_return_typeClarifying insert_return_type

P0508R0 Die assoziativen Container mit eindeutigen Schlüsseln und die ungeordneten Container mit eindeutigen Schlüsseln besitzen die Memberfunktion insert, die einen geschachtelten insert_return_type-Typ zurückgibt.P0508R0 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. Dieser Rückgabetyp ist nun als Spezialisierung eines Typs definiert, der für den Iterator und NodeType des Containers parametrisiert ist.That return type is now defined as a specialization of a type that is parameterized on the Iterator and NodeType of the container.

Inlinevariablen für die StandardbibliothekInline variables for the standard library

P0607R0P0607R0

Veraltete Features aus Anhang DAnnex D features deprecated

Anhang D des C++-Standards enthält alle Features, die veraltet sind. Dazu gehören auch shared_ptr::unique(), <codecvt> und namespace std::tr1.Annex D of the C++ standard contains all the features that have been deprecated, including shared_ptr::unique(), <codecvt>, and namespace std::tr1. Wenn der Compilerschalter /std:c++17 festgelegt wird, werden fast alle Features der Standardbibliothek in Anhang D als veraltet markiert.When the /std:c++17 compiler switch is set, almost all the standard library features in Annex D are marked as deprecated. Weitere Informationen finden Sie unter Features der Standardbibliothek in Anhang D sind als veraltet markiert.For more information, see Standard library features in Annex D are marked as deprecated.

Der std::tr2::sys-Namespace in <experimental/filesystem> gibt bei Verwendung von /std:c++14 jetzt standardmäßig eine Warnung zu veralteten Features aus und wird bei Verwendung von /std:c++17 standardmäßig entfernt.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.

Verbesserte Konformität in <iostream> durch Vermeidung einer nicht standardmäßigen Erweiterung (explizite Spezialisierungen in der Klasse).Improved conformance in <iostream> by avoiding a non-standard extension (in-class explicit specializations).

Die Standardbibliothek verwendet jetzt intern Variablenvorlagen.The standard library now uses variable templates internally.

Die Standardbibliothek wurde aufgrund von C++17-Compileränderungen aktualisiert.The standard library was updated in response to C++17 compiler changes. Dabei wurde u. a. noexcept im Typsystem hinzugefügt. Außerdem wurden dynamische Ausnahmespezifikationen entfernt.Updates include the addition of noexcept in the type system, and the removal of dynamic-exception-specifications.

Verbesserungen der Konformität in 15.6Conformance improvements in 15.6

C++17-Bibliotheksgrundlagen V1C++17 Library Fundamentals V1

P0220R1 integriert die technische Spezifikation der Bibliotheksgrundlagen für C++17 in die Standardbibliothek.P0220R1 incorporates Library Fundamentals Technical Specification for C++17 into the standard. Enthält Updates zu <experimental/tuple>, <experimental/optional>, <experimental/functional>, <experimental/any>, <experimental/string_view>, <experimental/memory>, <experimental/memory_resource>, und <experimental/algorithm>.Covers updates to <experimental/tuple>, <experimental/optional>, <experimental/functional>, <experimental/any>, <experimental/string_view>, <experimental/memory>, <experimental/memory_resource>, and <experimental/algorithm>.

C++17: Verbessern der Vorlagenargumentableitung für die StandardvorlagenbibliothekC++17: Improving class template argument deduction for the standard library

P0739R0 Verschieben Sie adopt_lock_t für scoped_lock an den Anfang der Parameterliste, um die konsistente Verwendung von scoped_lock zu ermöglichen.P0739R0 Move adopt_lock_t to front of parameter list for scoped_lock to enable consistent use of scoped_lock. Lassen Sie zu, dass der Konstruktor std::variant in mehreren Fällen Teil einer Überladungsauflösung ist, um die Kopierzuweisung zu ermöglichen.Allow std::variant constructor to participate in overload resolution in more cases, to enable copy assignment.

Verbesserungen der Konformität in 15.7Conformance improvements in 15.7

C++17: Umformulierung der KonstruktorvererbungC++17: Rewording inheriting constructors

P0136R1 gibt an, dass eine using -Deklaration, die einen Konstruktor benennt, jetzt die zugehörigen Basisklassenkonstruktoren für Initialisierungen der abgeleiteten Klasse sichtbar macht, anstatt die zusätzlichen abgeleiteten Klassenkonstruktoren zu deklarieren.P0136R1 specifies that a using declaration that names a constructor now makes the corresponding base class constructors visible to initializations of the derived class, rather than declaring additional derived class constructors. Diese Umformulierung ist eine Änderung gegenüber C++14.This rewording is a change from C++14. In Visual Studio 2017 Version 15.7 und höher kann Code, der im /std:c++17 -Modus in C++14 gültig ist und die Konstruktorvererbung verwendet, ungültig sein oder über eine andere Semantik verfügen.In Visual Studio 2017 version 15.7 and later, in /std:c++17 mode, code that is valid in C++14 and uses inheriting constructors may not be valid, or may have different semantics.

Im folgenden Beispiel ist das Verhalten von C++14 dargestellt:The following example shows C++14 behavior:

struct A {
    template<typename T>
    A(T, typename T::type = 0);
    A(int);
};

struct B : A {
    using A::A;
    B(int n) = delete; // Error C2280
};

B b(42L); // Calls B<long>(long), which calls A(int)
          //  due to substitution failure in A<long>(long).

Das folgende Beispiel zeigt das Verhalten bei Verwendung von /std:c++17 in Visual Studio 15.7:The following example shows /std:c++17 behavior in Visual Studio 15.7:

struct A {
    template<typename T>
    A(T, typename T::type = 0);
    A(int);
};

struct B : A {
    using A::A;
    B(int n)
    {
        //do something
    }
};

B b(42L); // now calls B(int)

Weitere Informationen finden Sie unter Konstruktoren.For more information, see Constructors.

C++17: Erweiterte AggregatinitialisierungC++17: Extended aggregate initialization

P0017R1P0017R1

Wenn der Konstruktor einer Basisklasse zwar nicht öffentlich, aber für eine abgeleitete Klasse verfügbar ist, können Sie im /std:c++17 -Modus in Visual Studio Version 2017 Version 15.7 nicht länger leere Klammern zum Initialisieren eines Objekts des abgeleiteten Typs verwenden.If the constructor of a base class is non-public, but accessible to a derived class, then under /std:c++17 mode in Visual Studio 2017 version 15.7 you can no longer use empty braces to initialize an object of the derived type. Im folgenden Beispiel ist das konforme Verhalten von C++14 dargestellt:The following example shows C++14 conformant behavior:

struct Derived;
struct Base {
    friend struct Derived;
private:
    Base() {}
};

struct Derived : Base {};
Derived d1; // OK. No aggregate init involved.
Derived d2 {}; // OK in C++14: Calls Derived::Derived()
               // which can call Base ctor.

In C++17 gilt Derived nun als Aggregattyp.In C++17, Derived is now considered an aggregate type. Das bedeutet, dass die Initialisierung von Base über den privaten Standardkonstruktor direkt als Teil der erweiterten Aggregatinitialisierungsregel erfolgt.It means that the initialization of Base via the private default constructor happens directly, as part of the extended aggregate initialization rule. Zuvor wurde der private Konstruktor Base über den Derived-Konstruktor aufgrund der Friend-Deklaration erfolgreich aufgerufen.Previously, the Base private constructor was called via the Derived constructor, and it succeeded because of the friend declaration. Das folgende Beispiel zeigt das C++17-Verhalten im /std:c++17 -Modus in Visual Studio Version 15.7:The following example shows C++17 behavior in Visual Studio version 15.7 in /std:c++17 mode:

struct Derived;
struct Base {
    friend struct Derived;
private:
    Base() {}
};
struct Derived : Base {
    Derived() {} // add user-defined constructor
                 // to call with {} initialization
};
Derived d1; // OK. No aggregate init involved.
Derived d2 {}; // error C2248: 'Base::Base': cannot access
               // private member declared in class 'Base'

C++17: Deklarieren von Nichttyp-Vorlagenparameter mit „auto“C++17: Declaring non-type template parameters with auto

P0127R2P0127R2

Im /std:c++17 -Modus kann der Compiler jetzt den Typ eines mit auto deklarierten Vorlagenarguments ohne Typ ableiten:In /std:c++17 mode, the compiler can now deduce the type of a non-type template argument that is declared with auto:

template <auto x> constexpr auto constant = x;

auto v1 = constant<5>;      // v1 == 5, decltype(v1) is int
auto v2 = constant<true>;   // v2 == true, decltype(v2) is bool
auto v3 = constant<'a'>;    // v3 == 'a', decltype(v3) is char

Eine Auswirkung dieses neuen Features ist, dass gültiger C++14-Code womöglich ungültig sein oder über eine andere Semantik verfügen kann.One impact of this new feature is that valid C++14 code may not be valid or may have different semantics. Beispielsweise sind einige Überladungen, die zuvor ungültig waren, nun gültig.For example, some overloads that were previously invalid are now valid. Das folgende Beispiel zeigt den C++14-Code, der kompiliert wird, weil der Aufruf an example(p) an example(void*); gebunden ist.The following example shows C++14 code that compiles because the call to example(p) is bound to example(void*);. In Visual Studio 2017 Version 15.7 stellt die example-Funktionsvorlage im /std:c++17 -Modus die beste Übereinstimmung dar.In Visual Studio 2017 version 15.7, in /std:c++17 mode, the example function template is the best match.

template <int N> struct A;
template <typename T, T N> int example(A<N>*) = delete;

void example(void *);

void sample(A<0> *p)
{
    example(p); // OK in C++14
}

Das folgende Beispiel zeigt den C++17-Code im /std:c++17 -Modus in Visual Studio 15.7:The following example shows C++17 code in Visual Studio 15.7 in /std:c++17 mode:

template <int N> struct A;
template <typename T, T N> int example(A<N>*);

void example(void *);

void sample(A<0> *p)
{
    example(p); // C2280: 'int example<int,0>(A<0>*)': attempting to reference a deleted function
}

C++17: Elementare Zeichenfolgenkonvertierungen (partiell)C++17: Elementary string conversions (partial)

P0067R5 Gebietsschemaunabhängige Funktionen auf niedriger Ebene für Wechsel zwischen ganzen Zahlen und Zeichenfolgen und zwischen Gleitkommazahlen und Zeichenfolgen.P0067R5 Low-level, locale-independent functions for conversions between integers and strings and between floating-point numbers and strings.

C++20: Vermeiden der unnötigen decay-Eigenschaft (partiell)C++20: Avoiding unnecessary decay (partial)

P0777R1 Fügt Differenzierung zwischen dem Konzept von „decay“ und der einfachen Entfernung von Konstanten- oder Verweisqualifizierern hinzu.P0777R1 Adds differentiation between the concept of "decay" and that of simply removing const or reference qualifiers. Die neue Typeigenschaft remove_reference_t ersetzt in einigen Kontexten decay_t.New type trait remove_reference_t replaces decay_t in some contexts. Die Unterstützung für remove_cvref_t ist in Visual Studio 2019 implementiert.Support for remove_cvref_t is implemented in Visual Studio 2019.

C++17: Parallele AlgorithmenC++17: Parallel algorithms

P0024R2 Die technische Spezifikation zur Parallelität ist mit nur wenigen Änderungen im Standard eingeschlossen.P0024R2 The Parallelism TS is incorporated into the standard, with minor modifications.

C++17: hypot(x, y, z)C++17: hypot(x, y, z)

P0030R1 Für die Typen float , double und long double werden drei neue Überladungen zu std::hypot hinzugefügt. Jeder dieser Typen verfügt über drei Eingabeparameter.P0030R1 Adds three new overloads to std::hypot, for types float, double, and long double, each of which has three input parameters.

C++17: <filesystem>C++17: <filesystem>

P0218R1 Übernimmt die Dateisystem-TS in die Standardversion, mit ein paar Veränderungen in der Formulierung.P0218R1 Adopts the File System TS into the standard with a few wording modifications.

C++17: Mathematische spezielle FunktionenC++17: Mathematical special functions

P0226R1 Übernimmt die vorherige technische Spezifikation für die mathematischen speziellen Funktionen in den Standardheader <cmath>.P0226R1 Adopts previous technical specifications for Mathematical Special Functions into the standard <cmath> header.

C++17: Herleitungsregelwerk für die StandardbibliothekC++17: Deduction guides for the standard library

P0433R2 Updates auf STL, um von der Nutzung von C++17 von P0091R3 zu profitieren, was Unterstützung für die Klassenvorlagenargumentableitung hinzufügt.P0433R2 Updates to STL to take advantage of C++17 adoption of P0091R3, which adds support for class template argument deduction.

C++17: Elementare ZeichenfolgenkonvertierungenC++17: Repairing elementary string conversions

P0682R1 Verschieben Sie die elementaren Funktionen für die Zeichenfolgenkonvertierung von P0067R5 in einen neuen Header, <charconv>, und führen Sie andere Verbesserungen durch, einschließlich der Fehlerbehandlung zur Verwendung von std::errc anstelle von std::error_code.P0682R1 Move the new elementary string conversion functions from P0067R5 into a new header <charconv> and make other improvements, including changing error handling to use std::errc instead of std::error_code.

C ++ 17: constexpr für char_traits (partiell)C++17: constexpr for char_traits (partial)

P0426R1 Änderungen an den std::traits_type-Memberfunktionen length, compare und find, damit std::string_view in konstanten Ausdrücken verfügbar wird.P0426R1 Changes to std::traits_type member functions length, compare, and find to make std::string_view usable in constant expressions. (In Visual Studio 2017 Version 15.6 wird dies nur für Clang/LLVM unterstützt.(In Visual Studio 2017 version 15.6, supported for Clang/LLVM only. In Version 15.7 Preview 2 ist die Unterstützung für CIXX ebenso fast vollständig.)In version 15.7 Preview 2, support is nearly complete for ClXX as well.)

Verbesserungen der Konformität in 15.9Conformance improvements in 15.9

Auswertungsreihenfolge von links nach rechts für die Operatoren ->*, [], >> und <<Left-to-right evaluation order for operators ->*, [], >>, and <<

Ab C++17 müssen die Operanden der Operatoren ->*, [], >> und << in der Reihenfolge von links nach rechts ausgewertet werden.Starting in C++17, the operands of the operators ->*, [], >>, and << must be evaluated in left-to-right order. Es gibt zwei Fälle, in denen der Compiler diese Reihenfolge nicht sicherstellen kann:There are two cases in which the compiler is unable to guarantee this order:

  • wenn es sich bei einem der Operandenausdrücke um ein nach Wert übergebenes Objekt handelt oder er ein nach Wert übergebenes Objekt enthält oderwhen one of the operand expressions is an object passed by value or contains an object passed by value, or

  • wenn er mithilfe von /clr kompiliert wird und einer der Operanden ein Feld eines Objekts oder ein Arrayelement ist.when compiled by using /clr, and one of the operands is a field of an object or an array element.

Der Compiler gibt die Warnung C4866 aus, wenn er die Auswertung von links nach rechts nicht sicherstellen kann.The compiler emits warning C4866 when it can't guarantee left-to-right evaluation. Diese Warnung wird vom Compiler nur generiert, wenn /std:c++17 oder höher angegeben ist, da die Anforderung der Auswertungsreihenfolge von links nach rechts für diese Operatoren in C++17 eingeführt wurde.The compiler generates this warning only if /std:c++17 or later is specified, as the left-to-right order requirement of these operators was introduced in C++17.

Um diese Warnung zu vermeiden, sollten Sie zunächst überprüfen, ob die Auswertung von links nach rechts für die Operanden erforderlich ist.To resolve this warning, first consider whether left-to-right evaluation of the operands is necessary. Dies kann beispielsweise erforderlich sein, wenn durch die Auswertung der Operanden reihenfolgenabhängige Nebenwirkungen auftreten.For example, it could be necessary when evaluation of the operands might produce order-dependent side-effects. In vielen Fällen hat die Reihenfolge, in der Operanden ausgewertet werden, keinen beobachtbaren Effekt.The order in which operands are evaluated has no observable effect in many cases. Wenn die Auswertungsreihenfolge von links nach rechts sein muss, überlegen Sie, ob Sie die Operanden stattdessen als const-Verweis übergeben können.If the order of evaluation must be left-to-right, consider whether you can pass the operands by const reference instead. Diese Änderung entfernt die Warnung im folgenden Codebeispiel:This change eliminates the warning in the following code sample:

// C4866.cpp
// compile with: /w14866 /std:c++17

class HasCopyConstructor
{
public:
    int x;

    HasCopyConstructor(int x) : x(x) {}
    HasCopyConstructor(const HasCopyConstructor& h) : x(h.x) { }
};

int operator>>(HasCopyConstructor a, HasCopyConstructor b) { return a.x >> b.x; }

// This version of operator>> does not trigger the warning:
// int operator>>(const HasCopyConstructor& a, const HasCopyConstructor& b) { return a.x >> b.x; }

int main()
{
    HasCopyConstructor a{ 1 };
    HasCopyConstructor b{ 2 };

    a>>b;        // C4866 for call to operator>>
};

Fehlerbehebungen in Visual Studio 2017 RTW Version 15.0Bug fixes in Visual Studio 2017 RTW (version 15.0)

copy-list-InitialisierungCopy-list-initialization

In Visual Studio 2017 werden ordnungsgemäß Compilerfehler im Zusammenhang mit der Objekterstellung bei Verwendung von Initialisiererlisten erzeugt.Visual Studio 2017 correctly raises compiler errors related to object creation using initializer lists. Diese Fehler wurden in Visual Studio 2015 nicht erfasst und konnten zu Abstürzen oder einem nicht definierten Laufzeitverhalten führen.These errors weren't caught in Visual Studio 2015, and could lead to crashes or undefined runtime behavior. Laut N4594 13.3.1.7p1 muss der Compiler in der copy-list-Initialisierung einen expliziten Konstruktor für die Überladungsauflösung berücksichtigen, muss jedoch einen Fehler auslösen, wenn die jeweilige Überladung ausgewählt wird.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 particular overload gets chosen.

Die folgenden beiden Beispiele kompilieren in Visual Studio 2015, aber nicht 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 &'

}

Verwenden Sie direkte Initialisierung, um den Fehler zu korrigieren:To correct the error, use direct initialization:

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

In Visual Studio 2015 behandelt der Compiler fälschlicherweise eine copy-list-Initialisierung auf die gleiche Weise wie eine Kopierinitialisierung. Er konvertiert nur die Konstruktoren für die Überladungsauflösung.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. Im folgenden Beispiel wählt Visual Studio 2015 MyInt(23), aber Visual Studio 2017 löst den Fehler ordnungsgemäß aus.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
}

Dieses Beispiel ähnelt dem vorherigen Beispiel, löst jedoch einen anderen Fehler aus.This example is similar to the previous one but raises a different error. Es ist in Visual Studio 2015 erfolgreich, und in Visual Studio 2017 mit C2668 schlägt es fehl.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
}

Veraltete TypeDefsDeprecated typedefs

Visual Studio 2017 gibt jetzt die richtige Warnung für veraltete TypeDefs aus, die in einer Klasse oder Struktur deklariert werden.Visual Studio 2017 now issues the correct warning for deprecated typedefs that are declared in a class or struct. Das folgende Beispiel wird ohne Warnung in Visual Studio 2015 kompiliert, erstellt jedoch 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
}

constexpr

Visual Studio 2017 löst ordnungsgemäß einen Fehler aus, wenn der linke Operand eines bedingten Auswertungsvorgangs in einem constexpr-Kontext ungültig ist.Visual Studio 2017 correctly raises an error when the left-hand operand of a conditionally evaluating operation isn't valid in a constexpr context. Der folgende Code wird in Visual Studio 2015 kompiliert, in Visual Studio 2017 jedoch nicht. Stattdessen wird „C3615 constexpr function 'f' cannot result in a constant expression“ ausgelöst:The following code compiles in Visual Studio 2015, but not in Visual Studio 2017, where it raises 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
}

Deklarieren Sie die Funktion array::size() als constexpr , oder entfernen Sie den constexpr -Qualifizierer aus f, um den Fehler zu beheben.To correct the error, either declare the array::size() function as constexpr or remove the constexpr qualifier from f.

Klassentypen, die an variadic-Funktionen übergeben werdenClass types passed to variadic functions

In Visual Studio 2017 müssen Klassen oder Strukturen, die an eine variadic-Funktion übergeben werden (z. B printf), einfach kopierbar sein.In Visual Studio 2017, classes or structs that are passed to a variadic function such as printf must be trivially copyable. Wenn solche Objekte übergeben werden, macht der Compiler einfach eine bitweise Kopie und ruft keinen Konstruktor oder Destruktor auf.When passing such objects, the compiler simply makes a bitwise copy and doesn't 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
}

Sie können eine Memberfunktion aufrufen, die einen einfachen kopierbaren Typ zurückgibt, um den Fehler zu beheben,To 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());

oder Sie verwenden eine statische Umwandlung, um das Objekt zu konvertieren, bevor es übergeben wird:or else use a static cast to convert the object before passing it:

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

Für mit CString erstellte und verwaltete Zeichenfolgen sollte der bereitgestellte operator LPCTSTR() verwendet werden, um ein CString-Objekt in einen C-Zeiger umzuwandeln, der von der Formatzeichenfolge erwartet wird.For strings built and managed using CString, the provided operator LPCTSTR() should be used to cast a CString object to the C pointer expected by the format string.

CString str1;
CString str2 = _T("hello!");
str1.Format(_T("%s"), static_cast<LPCTSTR>(str2));

CV-Qualifizierer in der KlassenkonstruktionCv-qualifiers in class construction

In Visual Studio 2015 ignoriert der Compiler beim Generieren eines Klassenobjekts über einen Konstruktoraufruf manchmal fälschlicherweise die CV-Qualifizierer.In Visual Studio 2015, the compiler sometimes incorrectly ignores the cv-qualifier when generating a class object via a constructor call. Dieses Problem kann potenziell zu einem Absturz oder zu unerwartetem Laufzeitverhalten führen.This issue can potentially cause a crash or unexpected runtime behavior. Das folgende Beispiel kompiliert in Visual Studio 2015, aber löst einen Compilerfehler in Visual Studio 2017 aus: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

Deklarieren Sie operator int() als const , um den Fehler zu beheben.To correct the error, declare operator int() as const.

Zugriff auf qualifizierte Namen in Vorlagen überprüfenAccess checking on qualified names in templates

In früheren Versionen des Compilers wurde der Zugriff auf qualifizierte Namen in bestimmten Kontexten von Vorlagen nicht überprüft.Previous versions of the compiler didn't check access to qualified names in some template contexts. Dieses Problem kann das erwartete SFINAE-Verhalten behindern, bei dem die Ersetzung aufgrund der Nichterreichbarkeit des Namens erwartungsgemäß fehlschlägt.This issue can interfere with expected SFINAE behavior, where the substitution is expected to fail because of the inaccessibility of a name. Dies konnte potenziell einen Absturz oder unerwartetes Verhalten zur Laufzeit auslösen, da der Compiler die falsche Überladung des Operators aufgerufen hat.It could have potentially caused a crash or unexpected behavior at runtime, because the compiler incorrectly called the wrong overload of the operator. In Visual Studio 2017 wird ein Compilerfehler ausgelöst.In Visual Studio 2017, a compiler error is raised. Welcher Fehler angezeigt wird, kann variieren, üblicherweise ist es jedoch „C2672 no matching overloaded function found“.The specific error might vary, but typically it's C2672 no matching overloaded function found. Der folgende Code kompiliert in Visual Studio 2015, aber löst in Visual Studio 2017 einen Fehler aus: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.
}

Fehlende VorlagenargumentlistenMissing template argument lists

In Visual Studio 2015 und früher wurde vom Compiler keine Diagnose für fehlende Vorlagenargumentlisten durchgeführt, wenn die Vorlage in einer Vorlagenparameterliste enthalten war: beispielsweise wenn ein Teil eines Standardvorlagenarguments oder ein Nichttyp-Vorlagenparameter fehlte.In Visual Studio 2015 and earlier, the compiler didn't diagnose missing template argument lists when the template appeared in a template parameter list: For example, when part of a default template argument or a non-type template parameter was missing. Dieses Problem kann zu unvorhersehbarem Verhalten führen, einschließlich des Absturzes des Compilers oder unerwartetem Laufzeitverhalten.This issue can result in unpredictable behavior, including compiler crashes or unexpected runtime behavior. Der folgende Code kompiliert in Visual Studio 2015, aber erzeugt in Visual Studio 2017 einen Fehler.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;

SFINAE für AusdrückeExpression-SFINAE

Um SFINAE für Ausdrücke zu unterstützen, analysiert der Compiler jetzt decltype -Argumente, wenn die Vorlagen deklariert statt instanziiert werden.To support expression-SFINAE, the compiler now parses decltype arguments when the templates are declared rather than instantiated. Wenn also eine nicht abhängige Spezialisierung im decltype-Argument gefunden wird, wird sie nicht auf die Instanziierungerungszeit zurückgestellt.Consequently, if a non-dependent specialization is found in the decltype argument, it's not deferred to instantiation-time. Es wird sofort verarbeitet, und alle daraus resultierenden Fehler werden sofort diagnostiziert.It's processed immediately, and any resulting errors are diagnosed at that time.

Das folgende Beispiel zeigt einen solchen Compilerfehler, der zum Zeitpunkt der Deklaration ausgelöst wird: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");

In anonymen Namespaces deklarierte KlassenClasses declared in anonymous namespaces

Entsprechend dem C++-Standard verfügt eine Klasse, die innerhalb eines anonymen Namespace deklariert wird, über interne Verknüpfungen und kann daher nicht exportiert werden.According to the C++ standard, a class declared inside an anonymous namespace has internal linkage, and that means it can't be exported. In Visual Studio 2015 und früheren Versionen wurde diese Regel nicht durchgesetzt.In Visual Studio 2015 and earlier, this rule wasn't enforced. In Visual Studio 2017 wird die Regel teilweise durchgesetzt.In Visual Studio 2017, the rule is partially enforced. In Visual Studio 2017 löst das folgende Beispiel den Fehler „C2201: const anonymous namespace::S1::vftable: must have external linkage in order to be exported/imported.“ ausIn Visual Studio 2017 the following example raises 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

Standardinitialisierer für Wertklassenmember (C++/CLI)Default initializers for value class members (C++/CLI)

In Visual Studio 2015 und früher, ließ der Compiler einen Standardmember-Initialisierer für einen Member einer Wertklasse zu, ignorierte diesen aber.In Visual Studio 2015 and earlier, the compiler permitted (but ignored) a default member initializer for a member of a value class. Standardinitialisierung einer Wertklasse initialisiert die Elemente immer auf null.Default initialization of a value class always zero-initializes the members. Ein Standardkonstruktor ist nicht zulässig.A default constructor isn't permitted. In Visual Studio 2017 lösen Standardmember-Initialisierer einen Compilerfehler aus, wie im folgenden Beispiel gezeigt: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
               // isn't allowed for a member of a value class
};

Standardindexer (C++/CLI)Default indexers (C++/CLI)

In Visual Studio 2015 und früher hat der Compiler in einigen Fällen fälschlicherweise eine Standardeigenschaft als einen Standardindexer kategorisiert.In Visual Studio 2015 and earlier, the compiler in some cases misidentified a default property as a default indexer. Das Problem konnte umgangen werden, indem der Bezeichner default für den Zugriff auf die Eigenschaft verwendet wurde.It was possible to work around the issue by using the identifier default to access the property. Diese Problemumgehung wurde selbst wiederum problematisch, nachdem default als Schlüsselwort in C++11 eingeführt wurde.The workaround itself became problematic after default was introduced as a keyword in C++11. In Visual Studio 2017 wurden die Fehler, für die eine Problemumgehung erforderlich war, behoben.In Visual Studio 2017, the bugs that required the workaround were fixed. Der Compiler löst jetzt einen Fehler aus, wenn für den Zugriff auf die Standardeigenschaft für eine Klasse default verwendet wird.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 können Sie anhand ihres Namens auf beide Eigenschaften zugreifen: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;
}

Fehlerbehebungen in 15.3Bug fixes in 15.3

Aufrufe gelöschter MembervorlagenCalls to deleted member templates

In früheren Versionen von Visual Studio gab der Compiler mitunter keine Fehlermeldung bei falsch formatierten Aufrufen einer gelöschten Membervorlage zurück.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. Durch diese Aufrufe wurden zur Laufzeit möglicherweise Abstürze verursacht.These calls would potentially cause crashes at runtime. Mit dem folgenden Code wird jetzt „C2280, 'int S<int>::f<int>(void)': attempting to reference a deleted function“ ausgelöst:The following code now produces C2280, 'int S<int>::f<int>(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
}

Um den Fehler zu beheben, deklarieren Sie i als int .To fix the error, declare i as int.

Voraussetzungsprüfungen für TypmerkmalePre-condition checks for type traits

Visual Studio 2017 Version 15.3 verbessert Voraussetzungsprüfungen für Typmerkmale so, dass der Standard strenger befolgt wird.Visual Studio 2017 version 15.3 improves pre-condition checks for type-traits to more strictly follow the standard. Eine solche Prüfung erfolgt für „assignable“.One such check is for assignable. Mit dem folgenden Code wird C2139 in Visual Studio 2017 Version 15.3 generiert: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

Neue Compilerwarnung und CLR-Prüfungen für Marshalling von nativ zu verwaltetNew compiler warning and runtime checks on native-to-managed marshaling

Aufrufe nativer Funktionen aus verwalteten Funktionen erfordern Marshalling.Calling from managed functions to native functions requires marshaling. Die CLR führt das Marshalling aus, versteht aber nicht die C++-Semantik.The CLR does the marshaling, but it doesn't understand C++ semantics. Wenn Sie ein natives Objekt nach Wert übergeben, ruft die CLR entweder den Kopierkonstruktor des Objekts auf oder verwendet BitBlt, was zu einem nicht definiertem Verhalten zur Laufzeit führt.If you pass a native object by value, CLR either calls the object's copy-constructor or uses BitBlt, which may cause undefined behavior at runtime.

Nun gibt der Compiler eine Warnung aus, wenn er zur Kompilierzeit erkennt, dass ein natives Objekt mit gelöschtem Kopierkonstruktor zwischen einer nativen und verwalteten Grenze nach Wert übergeben wird.Now the compiler emits a warning if it determines at compile time that a native object with deleted copy ctor is passed between a native and managed boundary by value. In den Fällen, in denen dem Compiler zur Kompilierzeit keine Informationen vorliegen, fügt er eine Laufzeitprüfung hinzu, sodass das Programm sofort std::terminate aufruft, sobald ein falsch formatiertes Marshalling erfolgt.For those cases in which the compiler doesn't know at compile time, it injects a runtime check so that the program calls std::terminate immediately when an ill-formed marshaling occurs. Mit dem folgenden Code wird in Version 15.3 von Visual Studio 2017 die Warnung „C4606 'A': passing argument by value across native and managed boundary requires valid copy constructor. Otherwise, the runtime behavior is undefined.“ generiertIn Visual Studio 2017 version 15.3, the following code produces warning C4606 'A': passing argument by value across native and managed boundary requires valid copy constructor. 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 marshaling. The CLR doesn't understand C++ and uses BitBlt, which results in a double-free later.
}

Um den Fehler zu beheben, entfernen Sie die Direktive #pragma managed, um den Aufrufer als nativ zu markieren und Marshalling zu vermeiden.To fix the error, remove the #pragma managed directive to mark the caller as native and avoid marshaling.

Warnung zu experimenteller API für WinRTExperimental API warning for WinRT

WinRT-APIs, die zu Experimentier- und Feedbackzwecken veröffentlicht werden, werden mit Windows.Foundation.Metadata.ExperimentalAttribute versehen.WinRT APIs that are released for experimentation and feedback are decorated with Windows.Foundation.Metadata.ExperimentalAttribute. In Visual Studio 2017 Version 15.3 generiert der Compiler die Warnung C4698 für dieses Attribut.In Visual Studio 2017 version 15.3, the compiler produces warning C4698 for this attribute. Einige APIs in früheren Versionen des Windows SDK wurden bereits mit dem Attribut markiert, sodass Aufrufe dieser APIs jetzt diese Compilerwarnung auslösen.A few APIs in previous versions of the Windows SDK have already been decorated with the attribute, and calls to these APIs now trigger this compiler warning. In neueren Windows SDKs wurde das Attribut in allen ausgelieferten Typen entfernt.Newer Windows SDKs have the attribute removed from all shipped types. Wenn Sie ein älteres SDK verwenden, müssen Sie diese Warnungen für alle Aufrufe an ausgelieferte Typen unterdrücken.If you're using an older SDK, you'll need to suppress these warnings for all calls to shipped types.

Mit dem folgenden Code wird die Warnung „C4698: 'Windows::Storage::IApplicationDataStatics2::GetForUserAsync' is for evaluation purposes only and is subject to change or removal in future updates“ generiert: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

Fügen Sie #pragma hinzu, um die Warnung zu deaktivieren:To disable the warning, add a #pragma:

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

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

#pragma warning(pop)

Out-of-Line-Definition einer VorlagenmemberfunktionOut-of-line definition of a template member function

Visual Studio 2017 Version 15.3 generiert einen Fehler für Out-of-Line-Definitionen einer Vorlagenmemberfunktion, die in der Klasse nicht deklariert wurde.Visual Studio 2017 version 15.3 produces an error for an out-of-line definition of a template member function that wasn't declared in the class. Mit dem folgenden Code wird jetzt der Fehler „C2039: 'f': is not a member of 'S'“ generiert: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'

Um den Fehler zu beheben, fügen Sie der Klasse eine Deklaration hinzu: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) {}

Es wird versucht, die Adresse eines this-Zeigers zu verwendenAttempting to take the address of this pointer

In C++ ist this ein prvalue des Typzeigers auf X. Sie können nicht die Adresse von this verwenden oder sie an einen lvalue-Verweis binden.In C++, this is a prvalue of type pointer to X. You can't take the address of this or bind it to an lvalue reference. In früheren Versionen von Visual Studio konnte es Ihnen der Compiler ermöglichen, diese Einschränkung mithilfe einer Umwandlung zu umgehen.In previous versions of Visual Studio, the compiler would allow you to circumvent this restriction by use of a cast. In Visual Studio 2017 Version 15.3 generiert der Compiler Fehler C2664.In Visual Studio 2017 version 15.3, the compiler produces error C2664.

Konvertierung in eine Basisklasse, auf die nicht zugegriffen werden kannConversion to an inaccessible base class

Visual Studio 2017 Version 15.3 generiert einen Fehler, wenn Sie versuchen, einen Typ in eine Basisklasse zu konvertieren, auf die nicht zugegriffen werden kann.Visual Studio 2017 version 15.3 produces an error when you attempt to convert a type to a base class that is inaccessible. Der Compiler löst jetzt den Fehler „C2243: 'type cast': conversion from 'D *' to 'B *' exists, but is inaccessible“ aus.The compiler now raises error C2243: 'type cast': conversion from 'D *' to 'B *' exists, but is inaccessible. Der folgende Code ist falsch formatiert und kann möglicherweise einen Absturz während der Laufzeit verursachen.The following code is ill-formed and can potentially cause a crash at runtime. Der Compiler generiert nun C2243, wenn er auf Code wie diesen trifft: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());
}

Standardargumente sind in Out-of-Line-Definitionen von Memberfunktionen nicht zulässigDefault arguments aren't allowed on out of line definitions of member functions

Standardargumente sind in Out-of-Line-Definitionen von Memberfunktionen in Vorlagenklassen nicht zulässig.Default arguments aren't allowed on out-of-line definitions of member functions in template classes. Der Compiler gibt bei Verwendung von /permissive eine Warnung und bei Verwendung von /permissive- einen schwerwiegenden Fehler aus.The compiler will issue a warning under /permissive, and a hard error under /permissive-.

In früheren Versionen von Visual Studio konnte der folgende falsch formatierte Code einen Absturz zur Laufzeit verursachen.In previous versions of Visual Studio, the following ill-formed code could potentially cause a runtime crash. In Visual Studio 2017 Version 15.3 wird die Warnung „C5034: 'A\<T>::f': an out-of-line definition of a member of a class template cannot have default arguments“ generiert:Visual Studio 2017 version 15.3 produces warning C5034: 'A\<T>::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
{
    // ...
}

Entfernen Sie das Standardargument = false, um den Fehler zu beheben.To fix the error, remove the = false default argument.

Verwenden von offsetof mit zusammengesetztem MemberkennzeichnerUse of offsetof with compound member designator

In Visual Studio 2017 Version 15.3 führt das Verwenden von offsetof(T, m), wobei m ein zusammengesetzter Memberkennzeichner ist, zu einer Warnung, wenn die Kompilierung mit der Option /Wall erfolgt.In Visual Studio 2017 version 15.3, using offsetof(T, m) where m is a "compound member designator" results in a warning when you compile with the /Wall option. Der folgende Code ist falsch formatiert und kann möglicherweise zur Laufzeit einen Absturz verursachen.The following code is ill-formed and could potentially cause a crash at runtime. In Version 15.3 von Visual Studio 2017 wird die Warnung „C4841: non-standard extension used: compound member designator in offsetof“ generiert:Visual Studio 2017 version 15.3 produces warning C4841: non-standard extension used: compound member designator in offsetof:

struct A {
   int arr[10];
};

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

Um den Code zu korrigieren, deaktivieren Sie die Warnung mit einem Pragma, oder ändern Sie den Code so, dass offsetof nicht verwendet wird: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)

Verwenden von offsetof mit statischem Datenmember oder mit MemberfunktionUsing offsetof with static data member or member function

In Visual Studio 2017 Version 15.3 führt das Verwenden von offsetof(T, m) zu einem Fehler, wenn m ein statischer Datenmember oder eine Memberfunktion ist.In Visual Studio 2017 version 15.3, using offsetof(T, m) where m refers to a static data member or a member function results in an error. Mit dem folgenden Code werden die Fehler „C4597: undefined behavior: offsetof applied to member function 'example'“ und „C4597: undefined behavior: offsetof applied to static data member 'sample'“ generiert:The following code produces error C4597: undefined behavior: offsetof applied to member function 'example' and error C4597: undefined behavior: offsetof applied to static data member 'sample':

#include <cstddef>

struct A {
   int ten() { return 10; }
   static constexpr int two = 2;
};

constexpr auto off = offsetof(A, ten);
constexpr auto off2 = offsetof(A, two);

Dieser Code ist falsch formatiert und kann möglicherweise zur Laufzeit einen Absturz verursachen.This code is ill-formed and could potentially cause a crash at runtime. Um den Fehler zu beheben, ändern Sie den Code so, dass das nicht definierte Verhalten nicht mehr aufgerufen wird.To fix the error, change the code to no longer invoke undefined behavior. Dies ist nicht portierbarer Code, der vom C++-Standard nicht zugelassen ist.It's non-portable code that's disallowed by the C++ standard.

Neue Warnung zu __declspec-AttributenNew warning on __declspec attributes

In Visual Studio 2017 Version 15.3 ignoriert der Compiler Attribute nicht mehr, wenn __declspec(...) vor der externen Verknüpfungsspezifikation extern "C" angewendet wird.In Visual Studio 2017 version 15.3, the compiler no longer ignores attributes if __declspec(...) is applied before extern "C" linkage specification. Zuvor hat der Compiler das Attribut ignoriert, was zu Problemen zur Laufzeit führen konnte.Previously, the compiler would ignore the attribute, which could have runtime implications. Bei Festlegung der Optionen /Wall und /WX wird mit dem folgenden Code die Warnung „C4768: __declspec attributes before linkage specification are ignored“ generiert:When the /Wall and /WX options are set, the following code produces warning C4768: __declspec attributes before linkage specification are ignored:

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

Um die Warnung zu korrigieren, fügen Sie zuerst extern "C" hinzu:To fix the warning, put extern "C" first:

extern "C" __declspec(noinline) HRESULT __stdcall

Diese Warnung ist in Version 15.3 standardmäßig deaktiviert (standardmäßig aktiviert in Version 15.5) und wirkt sich nur auf den mit /Wall /WX kompilierten Code aus.This warning is off by default in 15.3, but on by default in 15.5, and only impacts code compiled with /Wall /WX.

decltype und Aufrufe gelöschter Destruktorendecltype and calls to deleted destructors

In früheren Versionen von Visual Studio erkannte der Compiler nicht, wenn im Kontext des Ausdrucks, der decltype zugeordnet war, ein gelöschter Destruktor aufgerufen wurde.In previous versions of Visual Studio, the compiler didn't detect when a call to a deleted destructor occurred in the context of the expression associated with decltype. Mit dem folgenden Code wird in Version 15.3 von Visual Studio 2017 der Fehler „C2280: 'A<T>::~A(void)': attempting to reference a deleted function“ generiert:In Visual Studio 2017 version 15.3, the following code produces error C2280: 'A<T>::~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);
}

Nicht initialisierte „const“-VariablenUninitialized const variables

Das Visual Studio 2017 RTW-Release wies eine Regression auf, bei der der C++-Compiler keine Diagnose für eine nicht initialisierte const -Variable ausgab.Visual Studio 2017 RTW release had a regression: the C++ compiler wouldn't issue a diagnostic for an uninitialized const variable. Diese Regression wurde in Visual Studio 2017 Version 15.3 behoben.This regression has been fixed in Visual Studio 2017 version 15.3. Mit dem folgenden Code wird die Warnung „C4132: 'Value': const object should be initialized“ generiert:The following code now produces warning C4132: 'Value': const object should be initialized:

const int Value; //C4132

Um den Fehler zu beheben, weisen Sie Value einen Wert zu.To fix the error, assign a value to Value.

Leere DeklarationenEmpty declarations

Visual Studio 2017 Version 15.3 warnt bei leeren Deklarationen jetzt für alle Typen und nicht nur für integrierte Typen.Visual Studio 2017 version 15.3 now warns on empty declarations for all types, not just built-in types. Der folgende Code führt jetzt zur Warnung C4091, Stufe 2 für alle vier Deklarationen: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

Um die Warnungen zu entfernen, können Sie die leeren Deklarationen auskommentieren oder entfernen.To remove the warnings, comment-out or remove the empty declarations. In Fällen, in denen das nicht benannte Objekt einen Nebeneffekt haben soll (z. B. RAII), sollte es mit einem Namen versehen werden.In cases where the unnamed object is intended to have a side effect (such as RAII), it should be given a name.

Die Warnung wird bei Verwendung von /Wv:18 ausgeschlossen und ist auf der Warnstufe W2 standardmäßig aktiviert.The warning is excluded under /Wv:18 and is on by default under warning level W2.

std::is_convertible für Arraytypenstd::is_convertible for array types

Frühere Versionen des Compilers haben zu falschen Ergebnissen für std::is_convertible für Arraytypen geführt.Previous versions of the compiler gave incorrect results for std::is_convertible for array types. Daher mussten Bibliotheksautoren bei der Verwendung der Typeigenschaft std::is_convertible<...> besondere Schreibweisen für den Microsoft C++-Compiler anwenden.This required library writers to special-case the Microsoft C++ compiler when using the std::is_convertible<...> type trait. Im folgenden Beispiel sind die statischen Assertionen in früheren Versionen von Visual Studio erfolgreich, jedoch nicht in Visual Studio 2017 Version 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> wird berechnet, indem überprüft wird, ob eine imaginäre Funktionsdefinition wohlgeformt ist: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>(); }

Private Destruktoren und std::is_constructiblePrivate destructors and std::is_constructible

Frühere Versionen des Compilers ignorieren, ob ein Destruktor privat war, wenn über das Ergebnis von std::is_constructible entschieden wird.Previous versions of the compiler ignored whether a destructor was private when deciding the result of std::is_constructible. Dies wird nun berücksichtigt.It now considers them. Im folgenden Beispiel sind die statischen Assertionen in früheren Versionen von Visual Studio erfolgreich, jedoch nicht in Visual Studio 2017 Version 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);

Private Destruktoren führen dazu, dass ein Typ nicht konstruierbar ist.Private destructors cause a type to be non-constructible. std::is_constructible<T, Args...> wird berechnet, als würde die folgende Deklaration geschrieben:std::is_constructible<T, Args...> is calculated as if the following declaration were written:

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

Dieser Aufruf impliziert einen Destruktoraufruf.This call implies a destructor call.

C2668: Mehrdeutige ÜberladungsauflösungC2668: Ambiguous overload resolution

Frühere Versionen des Compilers konnten manchmal keine Mehrdeutigkeiten erkennen, wenn durch die Verwendung von sowohl Deklarationen als auch argumentabhängigen Lookups mehrere Kandidaten gefunden wurden.Previous versions of the compiler sometimes failed to detect ambiguity when it found multiple candidates via both using declarations and argument-dependent lookup. Dieser Fehler kann zum Auswählen der falschen Überladung und zu unerwartetem Laufzeitverhalten führen.This failure can lead to the wrong overload being chosen, and to unexpected runtime behavior. Im folgenden Beispiel löst Visual Studio 2017 Version 15.3 ordnungsgemäß „C2668 'f': ambiguous call to overloaded function“ aus: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
}

Um den Code zu korrigieren, entfernen Sie die Anweisung N::f, wenn Sie ::f() aufrufen wollten.To fix the code, remove the using N::f statement if you intended to call ::f().

C2660: Lokale Funktionsdeklarationen und argumentabhängiges LookupC2660: local function declarations and argument-dependent lookup

Lokale Funktionsdeklarationen verbergen die Funktitonsdeklaration im umschließenden Bereich und deaktivieren das argumentabhängige Lookup.Local function declarations hide the function declaration in the enclosing scope and disable argument-dependent lookup. In früheren Versionen des Compilers wurde in diesem Fall jedoch eine argumentabhängige Suche durchgeführt.However, previous versions of the compiler did perform argument-dependent lookup in this case. Dies könnte zum Auswählen der falschen Überladung und zu unerwartetem Laufzeitverhalten führen.It could potentially lead to the wrong overload being chosen, and unexpected runtime behavior. Der Fehler liegt in der Regel in einer falschen Signatur der lokalen Funktionsdeklaration.Typically, the error is because of an incorrect signature of the local function declaration. Im folgenden Beispiel löst Visual Studio 2017 Version 15.3 ordnungsgemäß „C2660 'f': function does not take two arguments“ aus:In the following example, Visual Studio 2017 version 15.3 correctly raises C2660 'f': function does not take two 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);
}

Um das Problem zu beheben, ändern Sie entweder die Signatur f(S), oder entfernen Sie diese.To fix the problem, either change the f(S) signature or remove it.

C5038: Reihenfolge der Initialisierung in InitialisiererlistenC5038: order of initialization in initializer lists

Klassenmember werden in der Reihenfolge initialisiert, in der sie deklariert werden, nicht in der Reihenfolge, in der Sie in Initialisiererlisten erscheinen.Class members are initialized in the order they're declared, not the order they appear in initializer lists. Frühere Versionen des Compilers haben keine Warnung ausgegeben, wenn sich die Reihenfolge der Initialisiererliste von der Deklarationsreihenfolge unterschied.Previous versions of the compiler didn't warn when the order of the initializer list differed from the order of declaration. Dieses Problem konnte zu undefiniertem Laufzeitverhalten führen, wenn die Initialisierung eines Members von einem anderen Member in der Liste abhing, der bereits initialisiert wurde.This issue could lead to undefined runtime behavior if one member's initialization depended on another member in the list already being initialized. Im folgenden Beispiel löst Visual Studio 2017 Version 15.3 (mit /Wall ) ordnungsgemäß die Warnung „C5038 data member 'A::y' will be initialized after data member 'A::x'“ aus: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;
};

Um das Problem zu beheben, ordnen Sie die Initialisiererliste so an, dass die Reihenfolge mit der Reihenfolge der Deklarationen übereinstimmt.To fix the problem, arrange the initializer list to have the same order as the declarations. Eine ähnliche Warnung wird ausgelöst, wenn ein oder beide Initialisierer auf Member der Basisklasse verweisen.A similar warning is raised when one or both initializers refer to base class members.

Diese Warnung ist standardmäßig deaktiviert und wirkt sich nur auf mit /Wall kompilierten Code aus.This warning is off-by-default, and only affects code compiled with /Wall.

Fehlerbehebungen und andere Verhaltensänderungen in 15.5Bug fixes and other behavior changes in 15.5

Teilweise Änderung der ReihenfolgePartial ordering change

Der Compiler weist nun den folgenden Code ordnungsgemäß zurück und gibt die richtige Fehlermeldung aus: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*)'

Das Problem im Beispiel oben ist, dass es zwei Unterschiede in den Typen gibt (const im Vergleich zu non-const und pack im Vergleich zu 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). Um den Compilerfehler zu beseitigen, entfernen Sie einen der Unterschiede.To eliminate the compiler error, remove one of the differences. Dies ermöglicht es dem Compiler, die Funktionen eindeutig zu sortieren.Then the compiler can 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);
}

AusnahmehandlerException handlers

Handler, die auf ein Array oder einen Funktionstyp verweisen, stimmen niemals mit einem Ausnahmeobjekt überein.Handlers of reference to array or function type are never a match for any exception object. Der Compiler hält sich nun ordnungsgemäß an diese Regel und gibt eine Warnung der Stufe 4 aus.The compiler now correctly honors this rule and raises a level 4 warning. Auch werden Handler von char* oder wchar_t* nicht mehr mit einem Zeichenfolgenliteral abgeglichen, wenn /Zc:strictStrings verwendet wird.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

Mit dem folgenden Code wird der Fehler vermieden:The following code avoids the error:

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

Der std::tr1-Namespace ist veraltet.std::tr1 namespace is deprecated

Der std::tr1-Namespace, der nicht dem Standard entspricht, ist nun sowohl im C++14- als auch im C++17-Modus als veraltet markiert.The non-standard std::tr1 namespace is now marked as deprecated in both C++14 and C++17 modes. In Visual Studio-2017 Version 15.5 löst der folgende Code C4996 aus: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.

Um den Fehler zu beheben, entfernen Sie den Verweis auf den tr1-Namespace: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;
}

Features der Standardbibliothek in Anhang D sind als veraltet markiertStandard library features in Annex D are marked as deprecated

Wenn der Compilerschalter im /std:c++17 -Modus festgelegt ist, werden fast alle Features der Standardbibliothek in Anhang D als veraltet markiert.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 Version 15.5 löst der folgende Code C4996 aus: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.

Um den Fehler zu beheben, befolgen Sie die Anweisungen im Text der Warnung, wie im folgenden Code gezeigt: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");

Unreferenzierte lokale VariablenUnreferenced local variables

In Visual Studio 15.5 wird die Warnung C4189 in den meisten Fällen ausgegeben, wie im folgenden Code gezeigt: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

Um den Fehler zu beheben, entfernen Sie die nicht verwendete Variable.To fix the error, remove the unused variable.

Einzeilige KommentareSingle-line comments

In Visual Studio 2017 Version 15.5 werden die Warnungen C4001 und C4179 nicht mehr vom C-Compiler ausgegeben.In Visual Studio 2017 version 15.5, warnings C4001 and C4179 are no longer emitted by the C compiler. Zuvor wurden sie nur bei Verwendung des Compilerschalters /Za ausgegeben.Previously, they were only emitted under the /Za compiler switch. Die Warnungen werden nicht mehr benötigt, weil einzeilige Kommentare seit C99 Teil des C-Standards sind.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'

Wenn der Code nicht abwärtskompatibel sein muss, können Sie die Warnung vermeiden, indem Sie die C4001/C4179-Unterdrückung entfernen.When the code doesn't need to be backwards compatible, you can avoid the warning by removing the C4001/C4179 suppression. Wenn der Code abwärts kompatibel sein muss, unterdrücken Sie nur 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 */

__declspec-Attribute mit extern "C"-Verknüpfung__declspec attributes with extern "C" linkage

In früheren Versionen von Visual Studio hat der Compiler __declspec(...)-Attribute ignoriert, wenn __declspec(...) vor der extern "C"-Verknüpfungsspezifikation angewendet wurde.In earlier versions of Visual Studio, the compiler ignored __declspec(...) attributes when __declspec(...) was applied before the extern "C" linkage specification. Dieses Verhalten führte dazu, dass Code generiert wurde, den der Benutzer nicht beabsichtigt hatte (mit möglichen Auswirkungen auf die Laufzeit).This behavior caused code to be generated that user didn't intend, with possible runtime implications. Die Warnung wurde in Visual Studio Version 15.3 hinzugefügt, war aber standardmäßig deaktiviert.The warning was added in Visual Studio version 15.3, but was off by default. In Visual Studio 2017 Version 15.5 ist die Warnung standardmäßig aktiviert.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

Um den Fehler zu beheben, platzieren Sie die Verknüpfungsspezifikation vor dem Attribut __declspec:To fix the error, place the linkage specification before the __declspec attribute:

extern "C" __declspec(noinline) HRESULT __stdcall

Diese neue Warnung C4768 wird für einige Windows SDK-Header ausgegeben, die mit Visual Studio 2017 15.3 oder älter ausgeliefert wurden (Beispiel: Version 10.0.15063.0, auch bekannt als RS2 SDK).This new warning C4768 is 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). Spätere Versionen von Windows SDK-Headern (speziell ShlObj.h und ShlObj_core.h) wurden jedoch so korrigiert, dass sie diese Warnung nicht ausgeben.However, later versions of Windows SDK headers (specifically, ShlObj.h and ShlObj_core.h) have been fixed so that they don't produce the warning. Wenn Sie sehen, dass diese Warnung von Windows SDK-Headern ausgegeben wird, können Sie diese Aktionen ausführen:When you see this warning coming from Windows SDK headers, you can take these actions:

  1. Wechseln Sie zum neuesten Windows SDK, das mit Visual Studio 2017 Version 15.5 ausgeliefert wurde.Switch to the latest Windows SDK that came with Visual Studio 2017 version 15.5 release.

  2. Deaktivieren Sie die Warnung um den #include-Teil der Windows SDK-Headeranweisung: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)

Externe constexpr-VerknüpfungExtern constexpr linkage

In früheren Versionen von Visual Studio gab der Compiler immer eine interne constexpr -Variablenverknüpfung aus, selbst wenn die Variable als extern markiert wurde.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 Version 15.5 ermöglicht ein neuer Compilerschalter ( /Zc:externConstexpr ) das richtige, standardkonforme Verhalten.In Visual Studio 2017 version 15.5, a new compiler switch (/Zc:externConstexpr) enables correct, standards-conforming behavior. Letztendlich wird dieses Verhalten die Standardeinstellung sein.Eventually this behavior will become the default.

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

Wenn eine Headerdatei eine Variable enthält, die als extern constexpr deklariert ist, muss sie als __declspec(selectany) markiert werden, damit ihre doppelten Deklarationen richtig kombiniert werden:If a header file contains a variable declared extern constexpr, it needs to be marked __declspec(selectany) to have its duplicate declarations combined correctly:

extern constexpr __declspec(selectany) int x = 10;

typeid kann nicht für einen unvollständigen Klassentyp verwendet werdentypeid can't be used on incomplete class type

In früheren Versionen von Visual Studio ließ der Compiler fälschlicherweise den folgenden Code zu, was zu potenziell falschen Typinformationen führte.In earlier versions of Visual Studio, the compiler incorrectly allowed the following code, resulting in potentially incorrect type information. In Visual Studio 2017 Version 15.5 löst der Compiler ordnungsgemäß einen Fehler aus: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'

std::is_convertible-Zieltypstd::is_convertible target type

std::is_convertible erfordert, dass der Zieltyp ein gültiger Rückgabetyp ist.std::is_convertible requires the target type to be a valid return type. In früheren Versionen von Visual Studio ließ der Compiler fälschlicherweise abstrakte Typen zu, was zu falscher Überladungsauflösung und unbeabsichtigtem Laufzeitverhalten führen konnte.In earlier versions of Visual Studio, the compiler incorrectly allowed abstract types, which might lead to incorrect overload resolution and unintended runtime behavior. Der folgende Code löst jetzt ordnungsgemäß c2338 aus: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

Um den Fehler zu vermeiden, sollten Sie bei der Verwendung von is_convertible Zeigertypen vergleichen, da ein Vergleich ohne Zeigertyp möglicherweise zu einem Fehler führt, wenn ein Typ abstrakt ist: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");

Entfernen der dynamischen Ausnahmespezifikation und noexceptDynamic exception specification removal and noexcept

In C++17 ist throw() ein Alias für noexcept . throw(<type list>) und throw(...) werden entfernt, und bestimmte Typen können noexcept enthalten.In C++17, throw() is an alias for noexcept, throw(<type list>) and throw(...) are removed, and certain types may include noexcept. Diese Änderung kann zu Quellkompatibilitätsproblemen mit Code führen, der mit C++14 oder früher konform ist.This change can cause source compatibility issues with code that conforms to C++14 or earlier. Die Option /Zc:noexceptTypes- kann verwendet werden, um zur C++14-Version von noexcept zurückzukehren, während generell der C++17-Modus verwendet wird.The /Zc:noexceptTypes- switch can be used to revert to the C++14 version of noexcept while using C++17 mode in general. Dies ermöglicht es Ihnen, Ihren Quellcode zu aktualisieren, um ihn an C++17 anzupassen, ohne dass Sie Ihren gesamten throw()-Code zur gleichen Zeit neu schreiben müssen.It enables you to update your source code to conform to C++17 without having to rewrite all your throw() code at the same time.

Der Compiler diagnostiziert nun auch eine größere Anzahl nicht übereinstimmender Ausnahmespezifikationen in Deklarationen im C++17-Modus oder mit /permissive- mit der neuen Warnung C5043.The compiler also now diagnoses more mismatched exception specifications in declarations in C++17 mode or with /permissive- with the new warning C5043.

Der folgende Code generiert C5043 und C5040 in Visual Studio 2017 Version 15.5, wenn der Schalter /std:c++17 verwendet wird: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
};

Sie können die Fehler entfernen, während Sie weiterhin /std:c++17 verwenden, indem Sie entweder die Option /Zc:noexceptTypes- zur Befehlszeile hinzufügen oder Ihren Code aktualisieren, um wie im folgenden Beispiel gezeigt noexcept zu verwenden: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 { }
};

InlinevariablenInline variables

Statische constexpr-Datenmember sind nun implizit inline. Ihre Deklaration innerhalb einer Klasse ist nun also ihre Definition.Static constexpr data members are now implicitly inline, which means that their declaration within a class is now their definition. Die Verwendung einer Out-of-Line-Definition für einen statischen constexpr-Datenmember ist redundant und nun veraltet.Using an out-of-line definition for a static constexpr data member is redundant, and now deprecated. Wenn in Visual Studio 2017 Version 15,5 der Schalter /std:c++17 verwendet wird, generiert der folgende Code nun die Warnung „C5041 'size': out-of-line definition for constexpr static data member is not needed and is deprecated 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

extern "C" __declspec(...) Warnung C4768 jetzt standardmäßig aktiviertextern "C" __declspec(...) warning C4768 now on by default

Die Warnung wurde in Visual Studio Version 2017 Version 15.3 hinzugefügt, war aber standardmäßig deaktiviert.The warning was added in Visual Studio 2017 version 15.3, but was off by default. In Visual Studio 2017 Version 15.5 ist die Warnung standardmäßig aktiviert.In Visual Studio 2017 version 15.5, the warning is on by default. Weitere Informationen finden Sie unter Neue Warnung zu __-Attributen.For more information, see New warning on __declspec attributes.

Standardfunktionen und __declspec(nothrow)Defaulted functions and __declspec(nothrow)

Der Compiler erlaubte es bisher, Standardfunktionen mit __declspec(nothrow) zu deklarieren, wenn die entsprechenden Basis-/Memberfunktionen Ausnahmen zuließen.The compiler previously allowed defaulted functions to be declared with __declspec(nothrow) when the corresponding base/member functions permitted exceptions. Dieses Verhalten steht im Widerspruch zum C++-Standard und kann zur Laufzeit zu undefiniertem Verhalten führen.This behavior is contrary to the C++ standard and can cause undefined behavior at runtime. Der Standard verlangt, dass solche Funktionen als gelöscht definiert werden, wenn es eine Abweichung von der Ausnahmespezifikation gibt.The standard requires such functions to be defined as deleted if there's an exception specification mismatch. Bei Verwendung von /std:c++17 löst der folgende Code nun „C2280 attempting to reference a deleted function. Function was implicitly deleted because the explicit exception specification is incompatible with that of the implicit declaration.“ ausUnder /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
}

Um diesen Code zu korrigieren, entfernen Sie entweder __declspec(nothrow) aus der Standardfunktion, oder entfernen Sie = default, und geben Sie eine Definition für die Funktion zusammen mit der erforderlichen Ausnahmebehandlung an: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 und Teilspezialisierungennoexcept and partial specializations

Mit noexcept im Typsystem können Teilspezialisierungen für den Abgleich bestimmter aufrufbarer Typen möglicherweise nicht kompiliert werden oder nicht die primäre Vorlage auswählen. Der Grund hierfür ist eine fehlende Teilspezialisierung für Zeiger auf noexcept-Funktionen.With noexcept in the type system, partial specializations for matching particular "callable" types may not compile, or fail to choose the primary template, because of a missing partial specialization for pointers-to-noexcept-functions.

In solchen Fällen kann es erforderlich sein, zusätzliche Teilspezialisierungen hinzuzufügen, um die noexcept -Funktionszeiger und die noexcept -Zeiger auf Memberfunktionen zu verarbeiten.In such cases, you may need to add additional partial specializations to handle the noexcept function pointers and noexcept pointers to member functions. Diese Überladungen sind nur im /std:c++17 -Modus zulässig.These overloads are only legal in /std:c++17 mode. Wenn die Abwärtskompatibilität mit C++14 aufrechterhalten werden muss und Sie Code schreiben, den andere nutzen, sollten Sie diese neuen Überladungen innerhalb von #ifdef-Anweisungen schützen.If backwards-compatibility with C++14 must be maintained, and you're writing code that others consume, then you should guard these new overloads inside #ifdef directives. Wenn Sie in einem eigenständigen Modul arbeiten, können Sie anstelle von #ifdef-Wächtern einfach den Schalter /Zc:noexceptTypes- für die Kompilierung verwenden.If you're working in a self-contained module, then instead of using #ifdef guards you can just compile with the /Zc:noexceptTypes- switch.

Der folgende Code wird bei Verwendung von /std:c++14 kompiliert, bei Verwendung von /std:c++17 mit error C2027: use of undefined type 'A<T>' tritt jedoch ein Fehler auf:The following code compiles under /std:c++14 but fails under /std:c++17 with error C2027: use of undefined type 'A<T>':

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
}

Der folgende Code ist bei Verwendung von /std:c++17 erfolgreich, da der Compiler die neue Teilspezialisierung A<void (*)() noexcept> auswählt: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
}

Fehlerbehebungen und andere Verhaltensänderungen in 15.7Bug fixes and other behavior changes in 15.7

C++17: Standardargument in der primären KlassenvorlageC++17: Default argument in the primary class template

Diese Verhaltensänderung ist eine Vorbedingung für Vorlagenargumentableitung für Klassenvorlagen – P0091R3.This behavior change is a precondition for Template argument deduction for class templates - P0091R3.

Zuvor hat der Compiler das Standardargument in der primären Klassenvorlage ignoriert:Previously, the compiler ignored the default argument in the primary class template:

template<typename T>
struct S {
    void f(int = 0);
};

template<typename T>
void S<T>::f(int = 0) {} // Re-definition necessary

Im /std:c++17 -Modus in Visual Studio 2017 Version 15.7 wird das Standardargument nicht ignoriert:In /std:c++17 mode in Visual Studio 2017 version 15.7, the default argument isn't ignored:

template<typename T>
struct S {
    void f(int = 0);
};

template<typename T>
void S<T>::f(int) {} // Default argument is used

Abhängige NamensauflösungDependent name resolution

Diese Verhaltensänderung ist eine Vorbedingung für Vorlagenargumentableitung für Klassenvorlagen – P0091R3.This behavior change is a precondition for Template argument deduction for class templates - P0091R3.

Im folgenden Beispiel löst der Compiler in Visual Studio 15.6 und früher D::type zu B<T>::type in der primären Klassenvorlage auf.In the following example, the compiler in Visual Studio 15.6 and earlier resolves D::type to B<T>::type in the primary class template.

template<typename T>
struct B {
    using type = T;
};

template<typename T>
struct D : B<T*> {
    using type = B<T*>::type;
};

Für Version 15.7 von Visual Studio 2017 im Modus /std:c++17 ist das typename -Schlüsselwort in der using -Anweisung von D erforderlich. Wenn typename nicht vorhanden ist, löst der Compiler die Warnung C4346 ('B<T*>::type': dependent name is not a type) und den Fehler C2061 (syntax error: identifier 'type') aus:Visual Studio 2017 version 15.7, in /std:c++17 mode, requires the typename keyword in the using statement in D. Without typename, the compiler raises warning C4346: 'B<T*>::type': dependent name is not a type and error C2061: syntax error: identifier 'type':

template<typename T>
struct B {
    using type = T;
};

template<typename T>
struct D : B<T*> {
    using type = typename B<T*>::type;
};

C++17 [[nodiscard]]-Attribute: Anstieg der WarnstufeC++17: [[nodiscard]] attribute - warning level increase

In Visual Studio 2017 Version 15.7 wurde im /std:c++17 -Modus die Warnstufe von „C4834 discarding return value of function with 'nodiscard' attribute“ von W3 in W1 erhöht.In Visual Studio 2017 version 15.7 in /std:c++17 mode, the warning level of C4834 discarding return value of function with 'nodiscard' attribute is increased from W3 to W1. Sie können die Warnung mit einer Umwandlung zu void oder durch Übergabe von /wd:4834 an den Compiler deaktivieren.You can disable the warning with a cast to void, or by passing /wd:4834 to the compiler

[[nodiscard]] int f() { return 0; }

int main() {
    f(); // warning: discarding return value
         // of function with 'nodiscard'
}

Initialisierungsliste für Basisklassen für variadic-VorlagenkonstruktorenVariadic template constructor base class initialization list

In früheren Editionen von Visual Studio war eine Initialisierungsliste für Basisklassen für variadic-Vorlagenkonstruktoren, in der Vorlagenargumente fehlten, fälschlicherweise ohne Fehler zulässig.In previous editions of Visual Studio, a variadic template constructor base class initialization list that was missing template arguments was erroneously allowed without error. In Visual Studio 2017 Version 15.7 wird ein Compilerfehler ausgelöst.In Visual Studio 2017 version 15.7, a compiler error is raised.

Das folgende Codebeispiel in Version 15.7 von Visual Studio 2017 löst den Fehler „C2614: D<int>: illegal member initialization: 'B' is not a base or member“ aus.The following code example in Visual Studio 2017 version 15.7 raises error C2614: D<int>: illegal member initialization: 'B' is not a base or member.

template<typename T>
struct B {};

template<typename T>
struct D : B<T>
{

    template<typename ...C>
    D() : B() {} // C2614. Missing template arguments to B.
};

D<int> d;

Ändern Sie den B()-Ausdruck zu „B<T>T>()“, um den Fehler zu beheben.To fix the error, change the B() expression to B<T>().

constexpr-Aggregatinitialisierungconstexpr aggregate initialization

In früheren Versionen des C++-Compilers wurde die constexpr -Aggregatinitialisierung falsch behandelt.Previous versions of the C++ compiler incorrectly handled constexpr aggregate initialization. Der Compiler hat ungültigen Code akzeptiert, in dem die Aggregatinitialisierungsliste über zu viele Elemente verfügte und eine ungültige Codegenerierung erzeugte.The compiler accepted invalid code in which the aggregate-init-list had too many elements, and produced bad codegen for it. Ein Beispiel für einen solchen Code wird im Folgenden gezeigt:The following code is an example of such code:

#include <array>
struct X {
    unsigned short a;
    unsigned char b;
};

int main() {
    constexpr std::array<X, 2> xs = {
        { 1, 2 },
        { 3, 4 }
    };
    return 0;
}

In Visual Studio 2017 Version 15.7 Update 3 und höher löst das vorherige Beispiel jetzt „C2078 too many initializers“ aus.In Visual Studio 2017 version 15.7 update 3 and later, the previous example now raises C2078 too many initializers. Im unten stehenden Codebeispiel wird veranschaulicht, wie der Code behoben wird.The following example shows how to fix the code. Beim Initialisieren eines std::array mit geschachtelten „brace-init-list“-Objekten weisen Sie dem inneren Array selbst ein „braced-list“ zu:When initializing a std::array with nested brace-init-lists, give the inner array a braced-list of its own:

#include <array>
struct X {
    unsigned short a;
    unsigned char b;
};

int main() {
    constexpr std::array<X, 2> xs = {{ // note double braces
        { 1, 2 },
        { 3, 4 }
    }}; // note double braces
    return 0;
}

Fehlerbehebungen und Verhaltensänderungen in 15.8Bug fixes and behavior changes in 15.8

Bei sämtlichen Compileränderungen in Visual Studio 2017 Version 15.8 handelt es sich um Fehlerbehebungen und Verhaltensänderungen.The compiler changes in Visual Studio 2017 version 15.8 are all bug fixes and behavior changes. Sie sind im Folgenden aufgeführt:They're listed below:

typename für nicht qualifizierte Bezeichnertypename on unqualified identifiers

Im Modus /permissive- werden falsche typename -Schlüsselwörter für nicht qualifizierte Bezeichner in Definitionen von Aliasvorlagen vom Compiler nicht mehr akzeptiert.In /permissive- mode, spurious typename keywords on unqualified identifiers in alias template definitions are no longer accepted by the compiler. Mit dem folgenden Code wird nun „C7511 'T': 'typename' keyword must be followed by a qualified name“ generiert.The following code now produces C7511 'T': 'typename' keyword must be followed by a qualified name:

template <typename T>
using  X = typename T;

Ändern Sie die zweite Zeile in using X = T;, um den Fehler zu beheben.To fix the error, change the second line to using X = T;.

__declspec() auf der rechten Seite der Definitionen von Aliasvorlagen__declspec() on right side of alias template definitions

__declspec ist auf der rechten Seite einer Aliasvorlagendefinition nicht mehr zulässig.__declspec is no longer permitted on the right-hand-side of an alias template definition. Zuvor hat der Compiler diesen Code akzeptiert, jedoch ignoriert.Previously, the compiler accepted but ignored this code. Bei Verwendung des Alias wurde keine Warnung zu veralteten Features generiert.It would never result in a deprecation warning when the alias was used.

Das C++-Standardattribut [[deprecated]] kann stattdessen verwendet werden und wird ab Visual Studio 2017 Version 15.6 eingehalten.The standard C++ attribute [[deprecated]] may be used instead, and is respected in Visual Studio 2017 version 15.6. Mit dem folgenden Code wird nun „C2760 syntax error: unexpected token '__declspec', expected 'type specifier'“ generiert:The following code now produces C2760 syntax error: unexpected token '__declspec', expected 'type specifier':

template <typename T>
using X = __declspec(deprecated("msg")) T;

Ersetzen Sie den Code mit dem Folgenden (mit den Attributen vor dem „=“ der Aliasdefinition), um den Fehler zu beheben:To fix the error, change to code to the following (with the attribute placed before the '=' of the alias definition):

template <typename T>
using  X [[deprecated("msg")]] = T;

Diagnose der ZweiphasennamenssucheTwo-phase name lookup diagnostics

Die Zweiphasennamenssuche erfordert, dass nicht abhängige Namen in Vorlagentexten zum Zeitpunkt der Definition für die Vorlage sichtbar sind.Two-phase name lookup requires that non-dependent names used in template bodies must be visible to the template at definition time. Zuvor hätte der Microsoft C++-Compiler einen nicht gefundenen Namen bis zu den Instanziierungszeitpunkten nicht gesucht.Previously, the Microsoft C++ compiler would leave an unfound name as not looked up until instantiation time. Nun müssen nicht abhängige Namen im Vorlagentext gebunden sein.Now, it requires that non-dependent names are bound in the template body.

Dies kann sich beispielsweise ergeben, wenn in abhängigen Basisklassen gesucht wird.One way this can manifest is with lookup into dependent base classes. Zuvor war im Compiler die Verwendung von Namen zulässig, die in abhängigen Basisklassen definiert sind.Previously, the compiler allowed the use of names that are defined in dependent base classes. Der Grund dafür ist, dass diese Namen bei der Instanziierung ermittelt wurden, wenn alle Typen aufgelöst werden.That's because they'd be looked up during instantiation time when all the types are resolved. Nun wird dieser Code als Fehler behandelt.Now that code is treated as an error. In diesen Fällen können Sie erzwingen, dass nach der Variable zum Instanziierungszeitpunkt gesucht wird, indem Sie sie mit dem Basisklassentyp qualifizieren oder anderweitig abhängig machen, indem Sie beispielsweise einen this->-Pointer hinzufügen.In these cases, you can force the variable to be looked up at instantiation time by qualifying it with the base class type or otherwise making it dependent, for example, by adding a this-> pointer.

Im Modus /permissive- erzeugt der folgende Code nun „C3861: 'base_value': identifier not found“:In /permissive- mode, the following code now raises C3861: 'base_value': identifier not found:

template <class T>
struct Base {
    int base_value = 42;
};

template <class T>
struct S : Base<T> {
    int f() {
        return base_value;
    }
};

Ändern Sie die Anweisung return in return this->base_value;, um den Fehler zu beheben.To fix the error, change the return statement to return this->base_value;.

Hinweis: In der Boost-Python-Bibliothek ist eine MSVC-spezifische Problemumgehung für eine Vorlagenvorwärtsdeklaration in unwind_type.hpp vorhanden.Note: In the Boost python library, there's been an MSVC-specific workaround for a template forward declaration in unwind_type.hpp. Im /permissive--Modus ab Visual Studio 2017 Version 15.8 (_MSC_VER=1915) führt der MSVC-Compiler die argumentabhängige Namenssuche ordnungsgemäß aus.Under /permissive- mode starting in Visual Studio 2017 version 15.8 (_MSC_VER=1915), the MSVC compiler does argument-dependent name lookup (ADL) correctly. Das Verhalten entspricht jetzt dem Verhalten anderer Compiler, sodass diese Problemumgehung nicht mehr erforderlich ist.It's now consistent with other compilers, making this workaround guard unnecessary. Um den Fehler „C3861: 'unwind_type': identifier not found“ zu vermeiden, finden Sie unter PR 229 im Boost-Repository Informationen zum Aktualisieren der Headerdatei.To avoid error C3861: 'unwind_type': identifier not found, see PR 229 in the Boost repo to update the header file. Das Boost-Paket vcpkg wurde bereits gepatcht. Wenn Sie also Ihre Boost-Quellen aus vcpkg abrufen oder aktualisieren möchten, müssen Sie den Patch nicht separat anwenden.We've already patched the vcpkg Boost package, so if you get or upgrade your Boost sources from vcpkg then you don't need to apply the patch separately.

Vorwärtsdeklarationen und -definitionen im Namespace stdforward declarations and definitions in namespace std

Standardmäßig ist es in C++ nicht zulässig, dem Namespace std Vorwärtsdeklarationen oder -definitionen hinzuzufügen.The C++ standard doesn't allow a user to add forward declarations or definitions into namespace std. Das Hinzufügen von Deklarationen oder Definitionen in den Namespace std oder einen Namespace im Namespace std resultiert nun in nicht definiertem Verhalten.Adding declarations or definitions to namespace std or to a namespace within namespace std now results in undefined behavior.

Der Ort, an dem einige Standardbibliothekstypen definiert werden, soll zu einem zukünftigen Zeitpunkt verschoben werden.At some time in the future, Microsoft will move the location where some standard library types are defined. Durch diese Änderung wird vorhandener Code, der dem Namespace std Vorwärtsdeklarationen hinzufügt, unterbrochen.This change will break existing code that adds forward declarations to namespace std. Eine neue Warnung (C4643) hilft beim Identifizieren solcher Probleme mit der Quelle.A new warning, C4643, helps identify such source issues. Im /default -Modus ist die Warnung aktiviert, standardmäßig ist sie deaktiviert.The warning is enabled in /default mode and is off by default. Dies wirkt sich auf Programme aus, die mit /Wall oder /WX kompiliert werden.It will impact programs that are compiled with /Wall or /WX.

Mit dem folgenden Code wird jetzt „C4643: Forward declaring 'vector' in namespace std is not permitted by the C++ Standard“ ausgelöst.The following code now raises C4643: Forward declaring 'vector' in namespace std is not permitted by the C++ Standard.

namespace std {
    template<typename T> class vector;
}

Verwenden Sie anstelle einer Vorwärtsdeklaration eine include-Anweisung, um den Fehler zu beheben:To fix the error, use an include directive rather than a forward declaration:

#include <vector>

Auf sich selbst verweisende KonstruktorenConstructors that delegate to themselves

Der C++-Standard schlägt vor, dass ein Compiler eine Diagnose ausgeben soll, wenn ein delegierender Konstruktor an sich selbst delegiert.The C++ standard suggests that a compiler should emit a diagnostic when a delegating constructor delegates to itself. Der Microsoft C++-Compiler löst in den Modi /std:c++17 und /std:c++latest nun „C7535: 'X::X': delegating constructor calls itself“ aus.The Microsoft C++ compiler in /std:c++17 and /std:c++latest modes now raises C7535: 'X::X': delegating constructor calls itself.

Ohne diese Fehlermeldung wird das folgende Programm kompiliert, jedoch wird eine Endlosschleife erstellt:Without this error, the following program will compile but will generate an infinite loop:

class X {
public:
    X(int, int);
    X(int v) : X(v){}
};

Delegieren Sie an einen anderen Konstruktor, um die Endlosschleife zu vermeiden:To avoid the infinite loop, delegate to a different constructor:

class X {
public:

    X(int, int);
    X(int v) : X(v, 0) {}
};

offsetof mit konstanten Ausdrückenoffsetof with constant expressions

offsetof wurde bisher mithilfe eines Makros implementiert, das reinterpret_cast erfordert.offsetof has traditionally been implemented using a macro that requires a reinterpret_cast. Die Verwendung ist in Kontexten nicht zulässig, die einen konstanten Ausdruck erfordern, jedoch war es bisher im Microsoft C++-Compiler gültig.This usage is illegal in contexts that require a constant expression, but the Microsoft C++ compiler has traditionally allowed it. Das offsetof-Makro, das im Rahmen der Standardbibliothek enthalten ist, verwendet eine intrinsische Compiler-Funktion ( __builtin_offsetof), jedoch haben viele Personen den Makro-Trick verwendet, um offsetof selbst zu definieren.The offsetof macro that is shipped as part of the standard library correctly uses a compiler intrinsic (__builtin_offsetof), but many people have used the macro trick to define their own offsetof.

In Visual Studio 2017, Version 15.8, beschränkt der Compiler die Bereiche, in denen diese reinterpret_cast -Operatoren im Standardmodus auftreten können, damit der Code dem Standardverhalten von C++ besser entspricht.In Visual Studio 2017 version 15.8, the compiler constrains the areas that these reinterpret_cast operators can appear in the default mode, to help code conform to standard C++ behavior. Im Modus /permissive- sind die Einschränkungen sogar strenger.Under /permissive-, the constraints are even stricter. Wenn ein offsetof-Ergebnis an Stellen verwendet wird, an denen konstante Ausdrücke erforderlich sind, löst der Code möglicherweise die Warnung „C4644 usage of the macro-based offsetof pattern in constant expressions is non-standard; use offsetof defined in the C++ standard library instead“ oder „C2975 invalid template argument, expected compile-time constant expression“ aus.Using the result of an offsetof in places that require constant expressions may result in code that issues warning C4644 usage of the macro-based offsetof pattern in constant expressions is non-standard; use offsetof defined in the C++ standard library instead or C2975 invalid template argument, expected compile-time constant expression.

Mit dem folgenden Code wird C4644 im /default - oder /std:c++17 -Modus ausgelöst, im Modus /permissive- wird C2975 ausgelöst:The following code raises C4644 in /default and /std:c++17 modes, and C2975 in /permissive- mode:

struct Data {
    int x;
};

// Common pattern of user-defined offsetof
#define MY_OFFSET(T, m) (unsigned long long)(&(((T*)nullptr)->m))

int main()

{
    switch (0) {
    case MY_OFFSET(Data, x): return 0;
    default: return 1;
    }
}

Verwenden Sie offsetof wie über <cstddef> definiert, um den Fehler zu beheben:To fix the error, use offsetof as defined via <cstddef>:

#include <cstddef>

struct Data {
    int x;
};

int main()
{
    switch (0) {
    case offsetof(Data, x): return 0;
    default: return 1;
    }
}

CV-Qualifizierer auf Basisklassen, die einer Paketerweiterung unterliegencv-qualifiers on base classes subject to pack expansion

Vorherige Versionen des Microsoft C++-Compilers haben nicht erkannt, dass Basisklassen über CV-Qualifizierer verfügen, wenn sie ebenfalls Paketerweiterungen unterliegen.Previous versions of the Microsoft C++ compiler didn't detect that a base-class had cv-qualifiers if it was also subject to pack expansion.

In Visual Studio 2017 Version 15.8 löst der folgende Code im Modus /permissive- die Warnung „C3770 'const S': is not a valid base class“ aus:In Visual Studio 2017 version 15.8, in /permissive- mode the following code raises C3770 'const S': is not a valid base class:

template<typename... T>
class X : public T... { };

class S { };

int main()
{
    X<const S> x;
}

template-Schlüsselwort und geschachtelte Namensspezifizierertemplate keyword and nested-name-specifiers

Im Modus /permissive- erfordert der Compiler nun das Schlüsselwort template , das einem Vorlagennamen vorangestellt wird, wenn dieser hinter einem abhängigen geschachtelten Namensspezifizierer steht.In /permissive- mode, the compiler now requires the template keyword to precede a template-name when it comes after a dependent nested-name-specifier.

Der folgende Code löst im Modus /permissive- nun „C7510: 'example': use of dependent template name must be prefixed with 'template'. note: see reference to class template instantiation 'X<T>' being compiled“ aus:The following code in /permissive- mode now raises C7510: 'example': use of dependent template name must be prefixed with 'template'. note: see reference to class template instantiation 'X<T>' being compiled:

template<typename T> struct Base
{
    template<class U> void example() {}
};

template<typename T>
struct X : Base<T>
{
    void example()
    {
        Base<T>::example<int>();
    }
};

Fügen Sie der Anweisung Base<T>::example<int>(); das Schlüsselwort template wie im folgenden Beispiel gezeigt hinzu, um den Fehler zu beheben:To fix the error, add the template keyword to the Base<T>::example<int>(); statement, as shown in the following example:

template<typename T> struct Base
{
    template<class U> void example() {}
};

template<typename T>
struct X : Base<T>
{
    void example()
    {
        // Add template keyword here:
        Base<T>::template example<int>();
    }
};

Fehlerbehebungen und Verhaltensänderungen in 15.9Bug fixes and behavior changes in 15.9

Bezeichner in MemberaliasvorlagenIdentifiers in member alias templates

Ein Bezeichner, der in einer Memberalias-Vorlagendefinition verwendet wird, muss vor der Verwendung deklariert werden.An identifier used in a member alias template definition must be declared before use.

In vorherigen Compilerversionen war der folgende Code zulässig:In previous versions of the compiler, the following code was allowed:

template <typename... Ts>
struct A
{
  public:
    template <typename U>
    using from_template_t = decltype(from_template(A<U>{}));

  private:
    template <template <typename...> typename Type, typename... Args>
    static constexpr A<Args...> from_template(A<Type<Args...>>);
};

A<>::from_template_t<A<int>> a;

In Visual Studio 2017 Version 15.9 löst der Compiler im /permissive--Modus „C3861: 'from_template': identifier not found“ aus.In Visual Studio 2017 version 15.9, in /permissive- mode, the compiler raises C3861: 'from_template': identifier not found.

Um den Fehler zu beheben, deklarieren Sie from_template_t vor from_template.To fix the error, declare from_template before from_template_t.

ModuländerungenModules changes

In Visual Studio 2017, Version 15.9 löst der Compiler immer dann den Fehler C5050 aus, wenn die Befehlszeilenoptionen für Module zwischen Modulerstellung und Modulverwendung nicht konsistent sind.In Visual Studio 2017, version 15.9, the compiler raises C5050 whenever the command-line options for modules aren't consistent between the module creation and module consumption sides. Im folgenden Beispiel liegen zwei Probleme vor:In the following example, there are two issues:

  • Auf der Verbraucherseite (main.cpp) ist die Option /EHsc nicht angegeben.On the consumption side (main.cpp), the option /EHsc isn't specified.

  • Die C++-Version lautet auf der Erstellerseite /std:c++17 und auf der Verbraucherseite /std:c++14 .The C++ version is /std:c++17 on the creation side, and /std:c++14 on the consumption side.

cl /EHsc /std:c++17 m.ixx /experimental:module
cl /experimental:module /module:reference m.ifc main.cpp /std:c++14

Der Compiler löst in beiden Fällen die Warnung C5050 aus: warning C5050: Possible incompatible environment while importing module 'm': mismatched C++ versions. Current "201402" module version "201703".The compiler raises C5050 for both of these cases: warning C5050: Possible incompatible environment while importing module 'm': mismatched C++ versions. Current "201402" module version "201703".

Darüber hinaus löst der Compiler immer dann einen C7536-Fehler aus, wenn die IFC-Datei geändert wurde.The compiler also raises C7536 whenever the .ifc file has been tampered with. Der Header der Modulschnittstelle enthält einen SHA2-Hash der darunter befindlichen Inhalte.The header of the module interface contains an SHA2 hash of the contents below it. Beim Import wird die IFC-Datei gehasht und dann mit dem im Header angegebenen Hash verglichen.On import, the .ifc file is hashed, then checked against the hash provided in the header. Wenn diese nicht übereinstimmen, wird der Fehler C7536 ausgelöst: ifc failed integrity checks. Expected SHA2: '66d5c8154df0c71d4cab7665bab4a125c7ce5cb9a401a4d8b461b706ddd771c6'.If these don't match, error C7536 is raised: ifc failed integrity checks. Expected SHA2: '66d5c8154df0c71d4cab7665bab4a125c7ce5cb9a401a4d8b461b706ddd771c6'.

Teilsortierung im Zusammenhang mit Aliasen und nicht abgeleiteten KontextenPartial ordering involving aliases and non-deduced contexts

Es besteht ein Implementierungsunterschied bei den Regeln für die Teilsortierung im Zusammenhang mit Aliasen in nicht abgeleiteten Kontexten.Implementations diverge in the partial ordering rules involving aliases in non-deduced contexts. Im folgenden Beispiel lösen GCC und der Microsoft C++-Compiler (im Modus /permissive-) einen Fehler aus, während Clang den Code akzeptiert.In the following example, GCC and the Microsoft C++ compiler (in /permissive- mode) raise an error, while Clang accepts the code.

#include <utility>
using size_t = std::size_t;

template <typename T>
struct A {};
template <size_t, size_t>
struct AlignedBuffer {};
template <size_t len>
using AlignedStorage = AlignedBuffer<len, 4>;

template <class T, class Alloc>
int f(Alloc &alloc, const AlignedStorage<T::size> &buffer)
{
    return 1;
}

template <class T, class Alloc>
int f(A<Alloc> &alloc, const AlignedStorage<T::size> &buffer)
{
    return 2;
}

struct Alloc
{
    static constexpr size_t size = 10;
};

int main()
{
    A<void> a;
    AlignedStorage<Alloc::size> buf;
    if (f<Alloc>(a, buf) != 2)
    {
        return 1;
    }

    return 0;
}

Das vorherige Beispiel löst C2668 aus:The previous example raises C2668:

partial_alias.cpp(32): error C2668: 'f': ambiguous call to overloaded function
partial_alias.cpp(18): note: could be 'int f<Alloc,void>(A<void> &,const AlignedBuffer<10,4> &)'
partial_alias.cpp(12): note: or       'int f<Alloc,A<void>>(Alloc &,const AlignedBuffer<10,4> &)'
        with
        [
            Alloc=A<void>
        ]
partial_alias.cpp(32): note: while trying to match the argument list '(A<void>, AlignedBuffer<10,4>)'

Der Grund für den Implementierungsunterschied ist eine Regression in der C++-Standardformulierung.The implementation divergence is because of a regression in the C++ standard wording. Bei der Lösung des Kernproblems 2235 wurde Text entfernt, der erlauben würde, dass diese Überladungen sortiert werden können.The resolution to core issue 2235 removed some text that would allow these overloads to be ordered. Der aktuelle C++-Standard bietet keinen Mechanismus für eine Teilsortierung dieser Funktionen, deshalb können sie als nicht eindeutig betrachtet werden.The current C++ standard doesn't provide a mechanism to partially order these functions, so they're considered ambiguous.

Als Problemumgehung wird empfohlen, sich nicht auf die Teilsortierung zum Lösen dieses Problems zu verlassen.As a workaround, we recommended that you not rely on partial ordering to resolve this problem. Verwenden Sie stattdessen SFINAE zum Entfernen von bestimmter Überladungen.Instead, use SFINAE to remove particular overloads. Im folgenden Beispiel wird eine Hilfsklasse IsA verwendet, um die erste Überladung zu entfernen, wenn Alloc eine Spezialisierung von A ist:In the following example, we use a helper class IsA to remove the first overload when Alloc is a specialization of A:

#include <utility>
using size_t = std::size_t;

template <typename T>
struct A {};
template <size_t, size_t>
struct AlignedBuffer {};
template <size_t len>
using AlignedStorage = AlignedBuffer<len, 4>;

template <typename T> struct IsA : std::false_type {};
template <typename T> struct IsA<A<T>> : std::true_type {};

template <class T, class Alloc, typename = std::enable_if_t<!IsA<Alloc>::value>>
int f(Alloc &alloc, const AlignedStorage<T::size> &buffer)
{
    return 1;
}

template <class T, class Alloc>
int f(A<Alloc> &alloc, const AlignedStorage<T::size> &buffer)
{
    return 2;
}

struct Alloc
{
    static constexpr size_t size = 10;
};

int main()
{
    A<void> a;
    AlignedStorage<Alloc::size> buf;
    if (f<Alloc>(a, buf) != 2)
    {
        return 1;
    }

    return 0;
}

Ungültige Ausdrücke und Nichtliteraltypen in Definitionen von VorlagenfunktionenIllegal expressions and non-literal types in templated function definitions

Ungültige Ausdrücke und Nichtliteraltypen werden nun richtig in Definitionen von Vorlagenfunktionen diagnostiziert, die explizit spezialisiert werden.Illegal expressions and non-literal types are now correctly diagnosed in the definitions of templated functions that are explicitly specialized. Bisher wurden solche Fehler nicht für die Funktionsdefinition ausgegeben.Previously, such errors weren't emitted for the function definition. Der ungültige Ausdruck oder Nichtliteraltyp wurde aber trotzdem diagnostiziert, wenn er als Teil eines konstanten Ausdrucks ausgewertet wurde.However, the illegal expression or non-literal type would still have been diagnosed if evaluated as part of a constant expression.

In früheren Versionen von Visual Studio wird der folgende Code ohne Warnung kompiliert:In previous versions of Visual Studio, the following code compiles without warning:

void g();

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

template<>
constexpr void S<int>::f()
{
    g(); // C3615 in 15.9
}

In Visual Studio 2017 Version 15.9 führt der Code zu diesem Fehler:In Visual Studio 2017 version 15.9, the code raises this error:

error C3615: constexpr function 'S<int>::f' cannot result in a constant expression.
note: failure was caused by call of undefined function or one not declared 'constexpr'
note: see usage of 'g'.

Entfernen Sie den Qualifizierer constexpr aus der expliziten Instanziierung der Funktion f(), um diesen Fehler zu vermeiden.To avoid the error, remove the constexpr qualifier from the explicit instantiation of the function f().

Verbesserungen der C++-Konformität in Visual Studio 2015C++ conformance improvements in Visual Studio 2015

Es ist eine vollständige Liste der Konformitätsverbesserungen bis Visual Studio 2015 Update 3 verfügbar.We have a complete list of conformance improvements up through Visual Studio 2015 Update 3. Weitere Informationen finden Sie unter Visual C++: Neuerungen 2003 bis 2015.For more information, see Visual C++ What's New 2003 through 2015.

Siehe auchSee also

Microsoft C++-Sprachkonformität: TabelleMicrosoft C++ language conformance table