Verbesserungen der C++-Konformität, Behavior Changes und Fehlerbehebungen in Visual Studio 2022

Microsoft C/C++ in Visual Studio (MSVC) nimmt bei jedem Release Verbesserungen bei der Konformität mit Standards sowie bei Fehlerbehebungen vor. In diesem Artikel werden die wesentlichen Verbesserungen nach Hauptrelease und dann nach Versionen aufgelistet. Um direkt zu den Änderungen für eine bestimmte Version zu springen, verwenden Sie die Links in diesem Artikel .

In diesem Dokument werden die Änderungen in Visual Studio 2022 aufgelistet.

Änderungen in Visual Studio 2019 finden Sie unter C++-Konformitätsverbesserungen in Visual Studio 2019.
Informationen zu den Änderungen in Visual Studio 2017 finden Sie unter Verbesserungen der C++-Konformität in Visual Studio 2017.
Änderungen in älteren Versionen finden Sie unter Visual C++ What's New 2003 bis 2015.

Konformitätsverbesserungen in Visual Studio 2022, Version 17.9

Visual Studio 2022, Version 17.9, enthält die folgenden Konformitätsverbesserungen, Fehlerkorrekturen und Verhaltensänderungen im Microsoft C/C++-Compiler.

Eine umfassendere Zusammenfassung der Änderungen an der Standardvorlagenbibliothek finden Sie unter STL Changelog VS 2022 17.9.

Anwendung eines strukturierten Typs _Alignas in C

In Versionen von Visual C++ vor Visual Studio 2022, Version 17.9, als _Alignas neben einem Strukturtyp in einer Deklaration angezeigt wurde, wurde sie nicht ordnungsgemäß gemäß iso-C Standard angewendet. Beispiel:

// compile with /std:c17
#include <stddef.h>
struct Outer
{
    _Alignas(32) struct Inner { int i; } member1;
    struct Inner member2;
};
static_assert(offsetof(struct Outer, member2)==4, "incorrect alignment");

Gemäß dem ISO-C-Standard sollte dieser Code ohne das static_assert Senden einer Diagnose kompiliert werden. Die _Alignas Direktive gilt nur für die Membervariable member1. Die Ausrichtung darf struct Innernicht geändert werden. Vor version 17.9.1 von Visual Studio wurde jedoch die Diagnose "falsche Ausrichtung" ausgegeben. Der Compiler wird an einem 32-Byte-Offset innerhalb struct Outerausgerichtetmember2.

Das Beheben dieser Änderung ist eine binäre Änderung, sodass beim Anwenden dieser Verhaltensänderung eine Warnung ausgegeben wird. Für den vorangehenden Code gilt Warnung C5274 nicht_Alignas mehr für den Typ "Inner" (gilt nur für deklarierte Datenobjekte)" wird jetzt auf Warnungsebene 1 ausgegeben.

In früheren Versionen von Visual Studio wurde ignoriert, _Alignas wenn sie neben einer anonymen Typdeklaration angezeigt wurde. Beispiel:

// compile with /std:c17
#include <stddef.h>
struct S {
    _Alignas(32) struct { int anon_member; };
    int k;
};
static_assert(offsetof(struct S, k)==4, "incorrect offsetof");
static_assert(sizeof(struct S)==32, "incorrect size");

Zuvor konnten beide static_assert Anweisungen beim Kompilieren dieses Codes nicht ausgeführt werden. Der Code wird jetzt kompiliert, aber mit den folgenden Warnungen der Ebene 1:

warning C5274: behavior change: _Alignas no longer applies to the type '<unnamed-tag>' (only applies to declared data objects)
warning C5273: behavior change: _Alignas on anonymous type no longer ignored (promoted members will align)

Wenn Sie das frühere Verhalten wünschen, ersetzen Sie es _Alignas(N) durch __declspec(align(N)). declspec(align) Im Gegensatz dazu _Alignaskann auf einen Typ angewendet werden.

__VA_OPT__ ist als Erweiterung unter /Zc:preprocessor

__VA_OPT__ wurde C++20 und C23 hinzugefügt. Vor seiner Hinzufügung gab es keine Standardmethode, um ein Komma in einem variadischen Makro zu elidieren. Um eine bessere Abwärtskompatibilität zu gewährleisten, __VA_OPT__ ist unter dem tokenbasierten Präprozessor /Zc:preprocessor in allen Sprachversionen aktiviert.

Dies kompiliert z. B. jetzt ohne Fehler:

#define LOG_WRAPPER(message, ...) WRITE_LOG(__LINE__, message __VA_OPT__(, __VA_ARGS__))

// Failed to build under /std:c11, now succeeds.
LOG_WRAPPER("Log message");
LOG_WRAPPER("Log message with %s", "argument")

C23-Sprache

Für C23 sind die folgenden Optionen verfügbar, wenn Sie den /std:clatest Compilerschalter verwenden:

typeof
typeof_unqual

Die folgenden Versionen sind für alle C-Sprachversionen verfügbar:

__typeof__
__typeof_unqual__

C++-Standardbibliothek

C++23-Features

  • formattable, range_format, format_kind, und set_debug_format() als Teil von P2286R8 Formatierungsbereiche
  • <mdspan> pro P0009R18 und nachfolgenden Wortänderungen, die auf den C++23 Standard angewendet wurden.
  • format() Zeiger pro P2510R3.

Verbesserungen der Konformität in Visual Studio 2022, Version 17.8

Visual Studio 2022, Version 17.8 bietet die folgenden Konformitätsverbesserungen, Fehlerbehebungen und Verhaltensänderungen im Microsoft C/C++ Compiler.

/FU gibt einen Fehler aus

Der C-Compiler hat bisher die /FU-Option akzeptiert, obwohl er die verwaltete Kompilierung bereits seit einiger Zeit nicht unterstützt. Er gibt jetzt einen Fehler aus. Projekte, die diese Option übergeben, müssen sie nur auf C++/CLI-Projekte beschränken.

C++-Standardbibliothek

Die C++23 benannten Module std und std.compat sind jetzt beim Kompilieren mit /std:c++20 verfügbar.

Eine umfassendere Zusammenfassung der Änderungen an der C++-Standardbibliothek finden Sie unter STL Changelog VS 2022 17.8.

Verbesserungen der Konformität in Visual Studio 2022, Version 17.7

Visual Studio 2022, Version 17.7 bietet die folgenden hervorgehobenen Konformitätsverbesserungen, Fehlerbehebungen und Verhaltensänderungen im Microsoft C/C++ Compiler.

/std:clatest zum C-Compiler hinzugefügt

Dieser Switch verhält sich wie der /std:c++latest-Switch für den C++-Compiler. Die Option ermöglicht alle derzeit implementierten Compiler- und Standardbibliotheksfunktionen, die für den nächsten Entwurf C-Standard vorgeschlagen werden, sowie einige in Bearbeitung befindliche und experimentelle Funktionen.

C++-Standardbibliothek

Die <print>-Bibliothek wird jetzt unterstützt. Siehe P2093R14 Formatierte Ausgabe.

views::cartesian_product implementiert.

Eine umfassendere Zusammenfassung der Änderungen an der Standardvorlagenbibliothek finden Sie unter STL Changelog VS 2022 17.7.

using-Konformität

Zuvor konnte die using-Anweisung dazu führen, dass Namen aus verwendeten Namespaces sichtbar bleiben, wenn sie dies nicht sollten. Dies kann dazu führen, dass eine nicht qualifizierte Namenssuche einen Namen in einem Namespace findet, auch wenn keine using-Anweisung aktiv ist.

Hier sind einige Beispiele für das neue und alte Verhalten.
Verweise in den folgenden Kommentaren auf „(1)“ bedeuten den Aufruf von f<K>(t) im Namespace A:

namespace A
{ 
    template<typename K, typename T> 
    auto f2(T t)
    { 
        return f<K>(t); // (1) Unqualified lookup should not find anything
    } 
} 

namespace B
{ 
    template<typename K, typename T> 
    auto f(T t) noexcept
    { // Previous behavior: This function was erroneously found during unqualified lookup at (1)
        return A::f2<K>(t); 
    } 
} 

namespace C
{ 
    template<typename T> 
    struct S {}; 

    template<typename, typename U> 
    U&& f(U&&) noexcept; // New behavior: ADL at (1) correctly finds this function 
} 

namespace D
{ 
    using namespace B; 

    void h()
    { 
        D::f<void>(C::S<int>()); 
    } 
} 

Dasselbe zugrunde liegende Problem kann dazu führen, dass Code, der zuvor kompiliert wurde, jetzt abgelehnt wird:

#include <memory>
namespace Addin {}
namespace Gui
{
    using namespace Addin;
}

namespace Addin
{
    using namespace std;
}

// This previously compiled, but now emits error C2065 for undeclared name 'allocator'.
// This should be declared as 'std::allocator<T*>' because the using directive nominating
// 'std' is not active at this point.
template <class T, class U = allocator<T*>>
class resource_list
{
};

namespace Gui
{
    typedef resource_list<int> intlist;
}

Verbesserte Konformität in Visual Studio 2022, Version 17.6

Visual Studio 2022, Version 17.6 bietet die folgenden Konformitätsverbesserungen, Fehlerbehebungen und Verhaltensänderungen im Microsoft C/C++ Compiler.

volatile-Verbundzuweisungen nicht länger veraltet

In C++20 wurde die Anwendung bestimmter Operatoren auf Typen, die mit volatile qualifiziert waren, als veraltet eingestuft. Angenommen, der folgende Code wird mit cl /std:c++20 /Wall test.cpp kompiliert:

void f(volatile int& expr)
{
   ++expr;
}

In diesem Fall erzeugt der Compiler die folgende Warnung: test.cpp(3): warning C5214: applying '++' to an operand with a volatile qualified type is deprecated in C++20.

In C++20 wurden Verbundzuweisungsoperatoren (Operatoren der Form @=) als veraltet eingestuft. In C++23 werden die in C++20 ausgeschlossenen Verbundoperatoren nicht mehr als veraltet eingestuft. In C++23 führt der folgende Code beispielsweise nicht zu einer Warnung, während in C++20 eine Warnung ausgegeben wird:

void f(volatile int& e1, int e2)
{
   e1 += e2;
}

Weitere Informationen zu dieser Änderung finden Sie unter CWG:2654.

Umschreibung von Gleichheitsausdrücken kein Breaking Change (P2468R2)

In C++20 wurde der Compiler durch P2468R2 so geändert, dass er Code wie den folgenden akzeptiert:

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

Der Compiler akzeptiert diesen Code, das heißt, dass der Compiler Code wie diesen strikter handhabt:

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

bool b = S{} == S{};

Version 17.5 des Compilers akzeptiert dieses Programm. Version 17.6 des Compilers lehnt ihn ab. Um dies zu beheben, fügen Sie const zu operator== hinzu, um die Mehrdeutigkeit zu beseitigen. Oder fügen Sie der Definition einen entsprechenden operator!= hinzu, wie im folgenden Beispiel gezeigt:

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

bool b = S{} == S{};

Die Microsoft C/C++-Compilerversionen 17.5 und 17.6 akzeptieren das vorherige Programm und rufen S::operator== in beiden Versionen auf.

Das in P2468R2 beschriebene allgemeine Programmiermodell besagt, dass bei Vorhandensein eines entsprechenden operator!= für einen Typ das Umschreibungsverhalten üblicherweise unterdrückt wird. Die vorgeschlagene Korrektur für Code, der zuvor in C++17 kompiliert wurde, ist das Hinzufügen eines entsprechenden operator!=. Weitere Informationen finden Sie unter Programmierungsmodell.

Verbesserungen der Konformität in Visual Studio 2022 Version 17.4

Die Version 17.4 von Visual Studio 2022 enthält die folgenden Konformitätsverbesserungen, Fehlerbehebungen und Behavior Changes im Microsoft C++-Compiler.

Zugrunde liegende Typen von enum ohne eigenen Gültigkeitsbereich und ohne festen Typ

In Visual Studio-Versionen vor Visual Studio 2022 Version 17.4 hat der C++-Compiler den zugrunde liegenden Typ einer Enumeration ohne eigenen Gültigkeitsbereich und ohne festen Basistyp nicht ordnungsgemäß ermittelt. Unter /Zc:enumTypes wird das Standardverhalten nun ordnungsgemäß implementiert.

Der C++-Standard erfordert, dass der zugrunde liegende Typ von enum groß genug ist, um alle Enumeratoren in dieser enumaufnehmen zu können. Ausreichend große Enumeratoren können den zugrunde liegenden Typ von enum auf unsigned int, long long oder unsigned long long festlegen. Bisher hatten solche enum-Typen im Microsoft-Compiler immer den zugrunde liegenden Typ int, unabhängig von den Enumeratorwerten.

Wenn die Option /Zc:enumTypes aktiviert wird, stellt sie eine potenzielle Quelle für Breaking Changes in Binärdateien dar. Sie ist standardmäßig deaktiviert und wird von /permissive- nicht aktiviert, da sich die Korrektur auf die Binärkompatibilität auswirken könnte. Einige Enumerationstypen ändern die Größe, wenn die entsprechende Korrektur aktiviert ist. Bestimmte Windows SDK-Header enthalten solche Enumerationsdefinitionen.

Beispiel

enum Unsigned
{
    A = 0xFFFFFFFF // Value 'A' does not fit in 'int'.
};

// Previously, failed this static_assert. Now passes with /Zc:enumTypes.
static_assert(std::is_same_v<std::underlying_type_t<Unsigned>, unsigned int>);

template <typename T>
void f(T x)
{
}

int main()
{
    // Previously called f<int>, now calls f<unsigned int>.
    f(+A);
}

// Previously this enum would have an underlying type of `int`, but Standard C++ requires this to have
// a 64-bit underlying type. Using /Zc:enumTypes changes the size of this enum from 4 to 8, which could
// impact binary compatibility with code compiled with an earlier compiler version or without the switch.
enum Changed
{
    X = -1,
    Y = 0xFFFFFFFF
};

Typen von Enumeratoren innerhalb einer enum-Definition ohne festen zugrunde liegenden Typ

In Visual Studio-Versionen vor Visual Studio 2022 Version 17.4 hat der C++-Compiler die Typen von Enumeratoren nicht ordnungsgemäß modelliert. Es konnte vorkommen, dass in Enumerationen ohne einen festen zugrunde liegenden Typ vor der schließende Klammer der Enumeration ein falscher Typ angenommen wurde. Unter /Zc:enumTypes implementiert der Compiler das Standardverhalten nun ordnungsgemäß.

Der C++-Standard legt fest, dass innerhalb einer Enumerationsdefinition, der kein fester Typ zugrunde liegt, die Typen der Enumeratoren durch Initialisierer bestimmt werden. Für Enumeratoren ohne Initialisierer kann der Typ des vorherigen Enumerators (unter Berücksichtigung eines Überlaufs) angenommen werden. Bisher erhielten solche Enumeratoren immer den abgeleiteten Typ der Enumeration mit einem Platzhalter für den zugrunde liegenden Typ (in der Regel int).

Wenn die Option /Zc:enumTypes aktiviert wird, stellt sie eine potenzielle Quelle für Breaking Changes in Binärdateien dar. Sie ist standardmäßig deaktiviert und wird von /permissive- nicht aktiviert, da sich die Korrektur auf die Binärkompatibilität auswirken könnte. Einige Enumerationstypen ändern die Größe, wenn die entsprechende Korrektur aktiviert ist. Bestimmte Windows SDK-Header enthalten solche Enumerationsdefinitionen.

Beispiel

enum Enum {
    A = 'A',
    B = sizeof(A)
};

static_assert(B == 1); // previously failed, now succeeds under /Zc:enumTypes

In diesem Beispiel sollte der Enumerator vor der schließenden geschweiften Klammer der Aufzählung eingegeben char werden, daher B sollte die Initialisierung mithilfe sizeof(char)der Enumerator A erfolgen. Vor der Korrektur von /Zc:enumTypes hatte A den Enumerationstyp Enum mit dem abgeleiteten zugrunde liegenden Typ int und B wurde mit sizeof(Enum) oder 4 initialisiert.

Konformitätsverbesserungen in Visual Studio 2022, Version 17.3

Die Version 17.3 von Visual Studio 2022 enthält die folgenden Konformitätsverbesserungen, Fehlerbehebungen und Behavior Changes im Microsoft C/ C++-Compiler.

C: Verbesserte Modifiziererkompatibilitätsprüfung zwischen Zeigern

Modifizierer zwischen Zeigern wurden vom C-Compiler nicht ordnungsgemäß verglichen. Das gilt insbesondere für void*. Dieser Fehler konnte dazu führen, dass fälschlicherweise eine Inkompatibilität zwischen const int** und void* sowie eine Kompatibilität zwischen int* volatile* und void* diagnostiziert wurde.

Beispiel

void fn(void* pv) { (pv); }

int main()
{
    int t = 42;
    int* pt = &t;
    int* volatile * i = &pt;
    fn(i);    // Now raises C4090
    const int** j = &pt;
    fn(j);    // No longer raises C4090
}

Verbesserungen der Konformität in Visual Studio 2022, Version 17.2

Die Version 17.2 von Visual Studio 2022 enthält die folgenden Konformitätsverbesserungen, Fehlerbehebungen und Behavior Changes im Microsoft C++-Compiler.

Unterminierte bidirektionale Zeichenwarnungen

Visual Studio 2022 Version 17.2 fügt Ebene 3 Warnung C5255 für unterminierte Unicode bidirektionale Zeichen in Kommentaren und Zeichenfolgen hinzu. Die Warnung behandelt ein Sicherheitsproblem, das in Trojanische Quelle: Unsichtbare Sicherheitsrisiken von Nicholas Boucher und Ross Anderson beschrieben wird. Weitere Informationen zu Unicode bidirektionalen Zeichen finden Sie unter Unicode® Standard Anhang #9: UNICODE BIDIRECTIONAL ALGORITHM.

Warnung C5255 adressiert nur Dateien, die nach der Konvertierung Unicode bidirektionale Zeichen enthalten. Diese Warnung gilt für UTF-8-, UTF-16- und UTF-32-Dateien, sodass die richtige Quellcodierung bereitgestellt werden muss. Diese Änderung ist ein Breaking Change der Quelle.

Beispiel (vor/nach)

In Versionen von Visual Studio vor Visual Studio 2022 Version 17.2 hat ein unterminiertes bidirektionales Zeichen keine Warnung erzeugt. In Visual Studio 2022 Version 17.2 wird die Warnung C5255 generiert:

// bidi.cpp
int main() {
    const char *access_level = "user";
    // The following source line contains bidirectional Unicode characters equivalent to:
    //    if ( strcmp(access_level, "user\u202e \u2066// Check if admin \u2069 \u2066") ) {
    // In most editors, it's rendered as:
    //    if ( strcmp(access_level, "user") ) { // Check if admin
    if ( strcmp(access_level, "user‮ ⁦// Check if admin ⁩ ⁦") ) {
        printf("You are an admin.\n");
    }
    return 0;
}

/* build output
bidi.cpp(8): warning C5255: unterminated bidirectional character encountered: 'U+202e'
bidi.cpp(8): warning C5255: unterminated bidirectional character encountered: 'U+2066'
*/

from_chars()float Tiebreaker

Visual Studio 2022 Version 17.2 behebt einen Fehler in <charconv>from_chars()float Tiebreaker-Regeln, die falsche Ergebnisse erzeugt haben. Dieser Fehler hat dezimale Zeichenfolgen betroffen, die sich an der genauen Mitte der aufeinander folgenden float Werte befinden, innerhalb eines schmalen Bereichs. (Die kleinsten und größten betroffenen Werte waren 32768.009765625 bzw 131071.98828125. Die Tiebreaker-Regel wollte auf "gerade" runden, und "gerade" ist "down", aber die Implementierung wurde falsch aufgerundet (double war nicht betroffen.) Weitere Informationen und Implementierungsdetails finden Sie unter microsoft/STL#2366.

Diese Änderung wirkt sich auf das Laufzeitverhalten im angegebenen Bereich von Fällen aus:

Beispiel

// from_chars_float.cpp
#include <cassert>
#include <charconv>
#include <cstdio>
#include <string_view>
#include <system_error>
using namespace std;
int main() {
    const double dbl  = 32768.009765625;
    const auto sv     = "32768.009765625"sv;
    float flt         = 0.0f;
    const auto result = from_chars(sv.data(), sv.data() + sv.size(), flt);
    assert(result.ec == errc{});
    printf("from_chars() returned: %.1000g\n", flt);
    printf("This rounded %s.\n", flt < dbl ? "DOWN" : "UP");
}

Versionen vor Version 17.2 von Visual Studio 2022:

C:\Temp>cl /EHsc /nologo /W4 /std:c++17 from_chars_float.cpp && from_chars_float
from_chars_float.cpp
from_chars() returned: 32768.01171875
This rounded UP.

In Visual Studio 2022, Version 17.2 und höher:

C:\Temp>cl /EHsc /nologo /W4 /std:c++17 from_chars_float.cpp && from_chars_float
from_chars_float.cpp
from_chars() returned: 32768.0078125
This rounded DOWN.

/Zc:__STDC__ stellt __STDC__ für C zur Verfügung

Der C-Standard erfordert, dass eine konforme C-Implementierung __STDC__ als 1 definiert. Aufgrund des Verhaltens der UCRT, die POSIX-Funktionen nicht verfügbar macht, wenn __STDC__1 ist, ist es nicht möglich, dieses Makro für C standardmäßig zu definieren, ohne Änderungen an den stabilen Sprachversionen einzuführen. In Visual Studio 2022 Version 17.2 und höher fügen Sie die Konformitätsoption /Zc:__STDC__ hinzu, die dieses Makro definiert. Es gibt keine negative Version der Option. Derzeit planen wir, diese Option standardmäßig für zukünftige Versionen von C zu verwenden.

Diese Änderung ist ein Breaking Change der Quelle. Es gilt, wenn der C11- oder C17-Modus aktiviert ist, /std:c11 oder /std:c17 zusammen mit /Zc:__STDC__.

Beispiel

// test__STDC__.c
#include <io.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
#if __STDC__
    int f = _open("file.txt", _O_RDONLY);
    _close(f);
#else
    int f = open("file.txt", O_RDONLY);
    close(f);
#endif
}

/* Command line behavior

C:\Temp>cl /EHsc /W4 /Zc:__STDC__ test__STDC__.c && test__STDC__

*/

Warnung für fehlende Klammern

Warnung C5246 meldet fehlende Klammern während der aggregierten Initialisierung eines Unterobjekts. Vor Visual Studio 2022 Version 17.2 behandelte die Warnung nicht den Fall eines Anonymen struct oder union.

Diese Änderung ist ein Breaking Change der Quelle. Es gilt, wenn die standardmäßige Warnung C5246 aktiviert ist.

Beispiel

In Visual Studio 2022 Version 17.2 und höher verursacht dieser Code jetzt einen Fehler:

struct S {
   union {
      float f[4];
      double d[2];
   };
};

void f()
{
   S s = { 1.0f, 2.0f, 3.14f, 4.0f };
}

/* Command line behavior
cl /Wall /c t.cpp

t.cpp(10): warning C5246: 'anonymous struct or union': the initialization of a subobject should be wrapped in braces
*/

Um dieses Problem zu beheben, fügen Sie dem Initializer Klammern hinzu:

void f()
{
   S s = { { 1.0f, 2.0f, 3.14f, 4.0f } };
}

Verbesserungen der Konformität in Visual Studio 2022, Version 17.1

Die Version 17.1 von Visual Studio 2022 enthält die folgenden Konformitätsverbesserungen, Fehlerbehebungen und Behavior Changes im Microsoft C++-Compiler.

Erkennung einer falsch formatierten Standarderfassung in nicht lokalen Lambdaausdrücken

Der C++-Standard lässt nur zu, dass ein Lambdaausdruck im Blockbereich einen Erfassungsstandard hat. In Visual Studio 2022, Version 17.1 und höher erkennt der Compiler, wenn eine Standarderfassung in einem nicht lokalen Lambdaausdruck unzulässig ist. Es sendet eine neue Warnung auf Ebene 4, C5253.

Diese Änderung ist ein Breaking Change der Quelle. Sie gilt in jedem Modus, der den neuen Lambdaprozessor verwendet: /Zc:lambda, /std:c++20 oder /std:c++latest.

Beispiel

In Visual Studio 2022 Version 17.1 gibt dieser Code nun einen Fehler aus:

#pragma warning(error:5253)

auto incr = [=](int value) { return value + 1; };

// capture_default.cpp(3,14): error C5253: a nonlocal lambda cannot have a capture default
// auto incr = [=](int value) { return value + 1; };
//              ^

Um dieses Problem zu beheben, entfernen Sie den Erfassungsstandard:

#pragma warning(error:5253)

auto incr = [](int value) { return value + 1; };

C4028 ist jetzt C4133 für Funktion-zu-Zeiger-Vorgänge

Vor Visual Studio 2022 Version 17.1 hat der Compiler bei bestimmten Zeiger-zu-Funktion-Vergleichen im C-Code eine falsche Fehlermeldung ausgegeben. Die falsche Meldung wurde ausgegeben, wenn Sie zwei Funktionszeiger mit gleicher Argumentanzahl, aber inkompatiblen Typen verglichen. Jetzt wird eine andere Warnung ausgegeben, die die Zeiger-zu-Funktion-Inkompatibilität und nicht die Nichtübereinstimmung von Funktionsparametern meldet.

Diese Änderung ist ein Breaking Change der Quelle. Sie gilt, wenn Code in C kompiliert wird.

Beispiel

int f1(int); 
int f2(char*); 
int main(void) 
{ 
    return (f1 == f2); 
}
// Old warning:
// C4028: formal parameter 1 different from declaration
// New warning:
// C4113: 'int (__cdecl *)(char *)' differs in parameter lists from 'int (__cdecl *)(int)'

Fehler bei nicht abhängigem static_assert-Ausdruck

Wenn der einem zugeordnete static_assert Ausdruck in Visual Studio 2022, Version 17.1 und höher, kein abhängiger Ausdruck ist, wertet der Compiler den Ausdruck aus, wenn er analysiert wird. Wenn der Ausdruck als false ausgewertet wird, gibt der Compiler eine Fehlermeldung aus. Vorher führte der Compiler diese Analyse nicht durch, wenn sich der static_assert innerhalb des Textkörpers einer Funktionsvorlage (oder innerhalb des Textkörpers einer Memberfunktion einer Klassenvorlage) befand.

Diese Änderung ist ein Breaking Change der Quelle. Sie gilt in jedem Modus, der /permissive- oder /Zc:static_assert beinhaltet. Dieser Behavior Change kann mithilfe der Compileroption /Zc:static_assert- deaktiviert werden.

Beispiel

In Visual Studio 2022 Version 17.1 und höher verursacht dieser Code jetzt einen Fehler:

template<typename T>
void f()
{
   static_assert(false, "BOOM!");
}

Um dieses Problem zu beheben, machen Sie den Ausdruck abhängig. Beispiel:

template<typename>
constexpr bool dependent_false = false;

template<typename T>
void f()
{
   static_assert(dependent_false<T>, "BOOM!");
}

Mit dieser Änderung gibt der Compiler nur dann eine Fehlermeldung aus, wenn die Funktionsvorlage f instanziiert wird.

Verbesserungen der Konformität in Visual Studio 2022 17.0

Die Version 17.0 von Visual Studio 2022 enthält die folgenden Konformitätsverbesserungen, Fehlerbehebungen und Behavior Changes im Microsoft C/C++-Compiler.

Warnung zur Bitfeldbreite für den Enumerationstyp

Wenn Sie eine Instanz eines Enumerationstyps als Bitfeld deklarieren, muss die Breite des Bitfelds alle möglichen Werte der Enumeration aufnehmen. Andernfalls gibt der Compiler eine Diagnosemeldung aus. Betrachten Sie das folgende Beispiel:

enum class E : unsigned { Zero, One, Two };

struct S {
  E e : 1;
};

Ein*e Programmierer*in erwartet möglicherweise, dass ein S::e-Klassenmember alle der explizit benannten enum-Werte enthalten kann. Aufgrund der Anzahl der Enumerationselemente ist dies nicht möglich. Das Bitfeld kann den Bereich der explizit bereitgestellten Werte von E (konzeptuell die Domäne von E) nicht abdecken. Um das Problem zu lösen, dass die Bitfeldbreite für die Domäne der Enumeration nicht groß genug ist, wird eine neue (standardmäßig deaktivierte) Warnung zu MSVC hinzugefügt:

t.cpp(4,5): warning C5249: 'S::e' of type 'E' has named enumerators with values that cannot be represented in the given bit field width of '1'.
  E e : 1;
    ^
t.cpp(1,38): note: see enumerator 'E::Two' with value '2'
enum class E : unsigned { Zero, One, Two };
                                     ^

Dieses Compilerverhalten ist ein quellbezogener und binärer Breaking Change, der sich auf alle /std - und /permissive -Modi auswirkt.

Fehler beim geordneten Zeigervergleich mit nullptr oder 0

Der C++-Standard hat versehentlich einen geordneten Zeigervergleich mit nullptr oder 0 zugelassen. Beispiel:

bool f(int *p)
{
   return p >= 0;
}

Im WG21-Papier N3478 wurde dieser Fehler entfernt. Diese Änderung wird in MSVC implementiert. Wenn das Beispiel mithilfe von /permissive- (und /diagnostics:caret ) kompilieren wird, wird der folgende Fehler ausgegeben:

t.cpp(3,14): error C7664: '>=': ordered comparison of pointer and integer zero ('int *' and 'int')
    return p >= 0;
             ^

Dieses Compilerverhalten ist ein quellbezogener und binärer Breaking Change, der sich auf Code auswirkt, der mithilfe von /permissive- in allen /std -Modi kompiliert wurde.

Siehe auch

Microsoft C/C++-Sprachkonformität