Peningkatan Kesesuaian C++, perubahan perilaku, dan perbaikan bug di Visual Studio 2022

Microsoft C/C++ di Visual Studio (MSVC) melakukan peningkatan kesesuaian dan perbaikan bug di setiap rilis. Artikel ini mencantumkan peningkatan signifikan berdasarkan rilis utama, lalu berdasarkan versi. Untuk melompat langsung ke perubahan untuk versi tertentu, gunakan tautan Di artikel ini.

Dokumen ini mencantumkan perubahan di Visual Studio 2022.

Untuk perubahan di Visual Studio 2019, lihat Peningkatan kesuaian C++ di Visual Studio 2019.
Untuk perubahan di Visual Studio 2017, lihat Peningkatan kesesuaian C++ di Visual Studio 2017.
Untuk perubahan dalam versi lama, lihat Visual C++ Apa yang Baru 2003 hingga 2015.

Peningkatan kesuaian di Visual Studio 2022 versi 17.9

Visual Studio 2022 versi 17.9 berisi peningkatan kesesuaian berikut, perbaikan bug, dan perubahan perilaku dalam pengompilasi Microsoft C/C++.

Untuk ringkasan perubahan yang lebih luas yang dibuat pada Pustaka Templat Standar, lihat STL Changelog VS 2022 17.9.

Aplikasi pada _Alignas jenis terstruktur di C

Dalam versi Visual C++ sebelum Visual Studio 2022 versi 17.9, ketika _Alignas muncul di samping jenis struktur dalam deklarasi, itu tidak diterapkan dengan benar sesuai dengan Standar ISO-C. Misalnya:

// 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");

Menurut ISO-C Standard, kode ini harus dikompilasi tanpa memancarkan static_assert diagnostik. Direktif _Alignas hanya berlaku untuk variabel member1anggota . Ini tidak boleh mengubah perataan struct Inner. Namun, sebelum rilis 17.9.1 visual Studio, diagnostik "penyelarasan yang salah" dipancarkan. Pengkompilasi selaras member2 dengan offset 32 byte dalam struct Outer.

Memperbaiki ini adalah perubahan pemecahan biner, jadi ketika perubahan perilaku ini diterapkan, peringatan dipancarkan. Untuk kode sebelumnya, Peringatan C5274, "_Alignas tidak lagi berlaku untuk jenis 'Dalam' (hanya berlaku untuk objek data yang dideklarasikan)" sekarang dipancarkan pada tingkat peringatan 1.

Di versi Visual Studio sebelumnya, _Alignas diabaikan ketika muncul di samping deklarasi jenis anonim. Misalnya:

// 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");

Sebelumnya, kedua static_assert pernyataan gagal saat mengkompilasi kode ini. Kode sekarang dikompilasi, tetapi dengan peringatan tingkat 1 berikut:

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)

Jika Anda menginginkan perilaku sebelumnya, ganti _Alignas(N) dengan __declspec(align(N)). Tidak seperti _Alignas, declspec(align) dapat diterapkan ke jenis.

__VA_OPT__ diaktifkan sebagai ekstensi di bawah /Zc:preprocessor

__VA_OPT__ ditambahkan ke C++20 dan C23. Sebelumnya untuk penambahannya, tidak ada cara standar untuk elide koma dalam makro variadik. Untuk memberikan kompatibilitas mundur yang lebih baik, __VA_OPT__ diaktifkan di bawah praprosesor /Zc:preprocessor berbasis token di semua versi bahasa.

Misalnya, sekarang ini dikompilasi tanpa kesalahan:

#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")

Bahasa C23

Untuk C23, berikut ini tersedia saat menggunakan sakelar /std:clatest kompilator:

typeof
typeof_unqual

Berikut ini tersedia untuk semua versi bahasa C:

__typeof__
__typeof_unqual__

Pustaka Standar C++

Fitur C++23

Peningkatan kesuaian di Visual Studio 2022 versi 17.8

Visual Studio 2022 versi 17.8 berisi peningkatan kesesuaian, perbaikan bug, dan perubahan perilaku berikut dalam kompilator Microsoft C/C++.

/FU mengeluarkan kesalahan

Pengkompilasi C digunakan untuk menerima /FU opsi, meskipun belum mendukung kompilasi terkelola selama beberapa waktu. Sekarang masalah kesalahan. Proyek yang meneruskan opsi ini hanya perlu membatasinya ke proyek C++/CLI.

Pustaka Standar C++

Modul std bernama C++23 dan std.compat sekarang tersedia saat mengkompilasi dengan /std:c++20.

Untuk ringkasan perubahan yang lebih luas yang dilakukan pada Pustaka Standar C++, lihat STL Changelog VS 2022 17.8.

Peningkatan kesuaian di Visual Studio 2022 versi 17.7

Visual Studio 2022 versi 17.7 berisi peningkatan kesesuaian yang disorot berikut, perbaikan bug, dan perubahan perilaku di pengompilasi Microsoft C/C++.

Ditambahkan /std:clatest ke pengkompilasi C

Sakelar ini berulah seperti /std:c++latest sakelar untuk pengkompilasi C++. Sakelar memungkinkan semua fitur kompiler dan pustaka standar yang saat ini diimplementasikan yang diusulkan untuk standar draf C berikutnya, serta beberapa fitur yang sedang berlangsung dan eksperimental.

Pustaka Standar C++

<print> Pustaka sekarang didukung. Lihat output P2093R14 Diformat.

Diimplementasikan views::cartesian_product.

Untuk ringkasan perubahan yang lebih luas yang dibuat pada Pustaka Templat Standar, lihat STL Changelog VS 2022 17.7.

using Kesesuaian

Sebelumnya, arahan using dapat menyebabkan nama dari namespace yang digunakan tetap terlihat ketika seharusnya tidak. Ini dapat menyebabkan pencarian nama yang tidak memenuhi syarat untuk menemukan nama di namespace bahkan ketika tidak using ada direktif aktif.

Berikut adalah beberapa contoh perilaku baru dan lama.
Referensi dalam komentar berikut ke "(1)" berarti panggilan ke f<K>(t) di 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>()); 
    } 
} 

Masalah yang mendasar yang sama dapat menyebabkan kode yang sebelumnya dikompilasi sekarang ditolak:

#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;
}

Peningkatan kesuaian di Visual Studio 2022 versi 17.6

Visual Studio 2022 versi 17.6 berisi peningkatan kesesuaian berikut, perbaikan bug, dan perubahan perilaku dalam kompilator Microsoft C/C++.

Penetapan gabungan volatile tidak lagi tidak digunakan lagi

C++20 tidak digunakan lagi menerapkan operator tertentu ke jenis yang memenuhi syarat dengan volatile. Misalnya, ketika kode berikut dikompilasi dengan cl /std:c++20 /Wall test.cpp:

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

Pengkompilasi menghasilkan test.cpp(3): warning C5214: applying '++' to an operand with a volatile qualified type is deprecated in C++20.

Di C++20, operator penugasan gabungan (operator formulir @=) tidak digunakan lagi. Di C++23, operator senyawa yang dikecualikan di C++20 tidak lagi tidak digunakan lagi. Misalnya, di C++23 kode berikut tidak menghasilkan peringatan, sedangkan kode ini terjadi di C++20:

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

Untuk informasi selengkapnya tentang perubahan ini, lihat CWG:2654

Menulis ulang kesetaraan dalam ekspresi kurang dari perubahan yang melanggar (P2468R2)

Di C++20, P2468R2 mengubah pengkompilasi untuk menerima kode seperti:

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

Pengkompilasi menerima kode ini, yang berarti bahwa pengkompilasi lebih ketat dengan kode seperti:

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

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

Versi 17.5 pengkompilasi menerima program ini. Compiler versi 17.6 menolaknya. Untuk memperbaikinya, tambahkan const ke untuk operator== menghapus ambiguitas. Atau, tambahkan yang sesuai dengan operator!= definisi seperti yang ditunjukkan dalam contoh berikut:

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

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

Pengkompilasi Microsoft C/C++ versi 17.5 dan 17.6 menerima program sebelumnya, dan memanggil S::operator== di kedua versi.

Model pemrograman umum yang diuraikan dalam P2468R2 adalah bahwa jika ada yang sesuai operator!= untuk jenis, biasanya menekan perilaku penulisan ulang. Menambahkan yang sesuai operator!= adalah perbaikan yang disarankan untuk kode yang sebelumnya dikompilasi di C++17. Untuk informasi selengkapnya, lihat Model Pemrograman.

Peningkatan kesuaian di Visual Studio 2022 versi 17.4

Visual Studio 2022 versi 17.4 berisi peningkatan kesesuaian berikut, perbaikan bug, dan perubahan perilaku dalam pengompilasi Microsoft C/C++.

Jenis yang mendasar tidak terlingkup enum tanpa jenis tetap

Dalam versi Visual Studio sebelum Visual Studio 2022 versi 17.4, pengkompilasi C++ tidak menentukan dengan benar jenis enumerasi yang tidak terlingkup dengan benar tanpa jenis dasar tetap. Di bawah /Zc:enumTypes, kami sekarang menerapkan perilaku standar dengan benar.

Standar C++ mengharuskan jenis yang mendasar dari yang enum cukup besar untuk menahan semua enumerator dalam .enum Enumerator yang cukup besar dapat mengatur jenis yang enum mendasar ke unsigned int, , long longatau unsigned long long. Sebelumnya, jenis tersebut enum selalu memiliki jenis int yang mendasar dalam kompilator Microsoft, terlepas dari nilai enumerator.

Saat diaktifkan, /Zc:enumTypes opsi adalah sumber potensial dan perubahan pemecahan biner. Ini nonaktif secara default, dan tidak diaktifkan oleh /permissive-, karena perbaikan dapat memengaruhi kompatibilitas biner. Beberapa jenis enumerasi berubah ukuran ketika perbaikan yang sesuai diaktifkan. Header Windows SDK tertentu menyertakan definisi enumerasi tersebut.

Contoh

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
};

Jenis enumerator dalam enum definisi tanpa jenis dasar tetap

Dalam versi Visual Studio sebelum Visual Studio 2022 versi 17.4, kompilator C++ tidak memodelkan jenis enumerator dengan benar. Ini dapat mengasumsikan jenis yang salah dalam enumerasi tanpa jenis yang mendasar tetap sebelum kurung kurawal penutup enumerasi. Di bawah /Zc:enumTypes, pengkompilasi sekarang mengimplementasikan perilaku standar dengan benar.

Standar C++ menentukan bahwa dalam definisi enumerasi tanpa jenis dasar tetap, penginisialisasi menentukan jenis enumerator. Atau, untuk enumerator tanpa inisialisasi, dengan jenis enumerator sebelumnya (memperhitungkan luapan). Sebelumnya, enumerator tersebut selalu diberi jenis enumerasi yang disimpulkan, dengan tempat penampung untuk jenis yang mendasar (biasanya int).

Saat diaktifkan, /Zc:enumTypes opsi adalah sumber potensial dan perubahan pemecahan biner. Ini nonaktif secara default, dan tidak diaktifkan oleh /permissive-, karena perbaikan dapat memengaruhi kompatibilitas biner. Beberapa jenis enumerasi berubah ukuran ketika perbaikan yang sesuai diaktifkan. Header Windows SDK tertentu menyertakan definisi enumerasi tersebut.

Contoh

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

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

Dalam contoh ini enumerator A harus memiliki jenis char sebelum kurung kurawal penutup enumerasi, jadi B harus diinisialisasi menggunakan sizeof(char). /Zc:enumTypes Sebelum perbaikan, A memiliki jenis Enum enumerasi dengan jenis intyang mendasar yang disimpulkan , dan B diinisialisasi menggunakan sizeof(Enum), atau 4.

Peningkatan kesuaian di Visual Studio 2022 versi 17.3

Visual Studio 2022 versi 17.3 berisi peningkatan kesesuaian berikut, perbaikan bug, dan perubahan perilaku dalam pengompilasi Microsoft C/C++.

C: Pemeriksaan kompatibilitas pengubah yang ditingkatkan antar pointer

Pengkompilasi C tidak membandingkan pengubah dengan benar antara penunjuk, terutama void*. Cacat ini dapat mengakibatkan diagnosis ketidakcocokan yang tidak tepat antara const int** dan void* dan kompatibilitas antara int* volatile* dan void*.

Contoh

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
}

Peningkatan kesesuaian di Visual Studio 2022 versi 17.2

Visual Studio 2022 versi 17.2 berisi peningkatan kesesuaian berikut, perbaikan bug, dan perubahan perilaku dalam pengompilasi Microsoft C/C++.

Peringatan karakter dua arah tanpa henti

Visual Studio 2022 versi 17.2 menambahkan peringatan tingkat 3 C5255 untuk karakter dua arah Unicode tanpa henti dalam komentar dan string. Peringatan tersebut membahas masalah keamanan yang dijelaskan dalam Sumber Trojan: Kerentanan Tak Terlihat oleh Nicholas Boucher dan Ross Anderson. Untuk informasi selengkapnya tentang karakter dua arah Unicode, lihat Lampiran Standar Unicode® #9: ALGORITMA DUA ARAH UNICODE.

Peringatan C5255 hanya membahas file yang, setelah konversi, berisi karakter dua arah Unicode. Peringatan ini berlaku untuk file UTF-8, UTF-16, dan UTF-32, sehingga pengodean sumber yang tepat harus disediakan. Perubahan ini adalah perubahan pemecah sumber.

Contoh (sebelum/sesudah)

Dalam versi Visual Studio sebelum Visual Studio 2022 versi 17.2, karakter dua arah tanpa henti tidak menghasilkan peringatan. Visual Studio 2022 versi 17.2 menghasilkan peringatan C5255:

// 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 versi 17.2 memperbaiki bug di aturan tiebreaker <charconv>from_chars()float yang menghasilkan hasil yang salah. Bug ini memengaruhi string desimal yang ada di titik tengah yang tepat dari nilai float berturut-turut, dalam rentang sempit. (Nilai terkecil dan terbesar yang terpengaruh adalah 32768.009765625 dan 131071.98828125, masing-masing.) Aturan pemecah tiebreaker ingin membulatkan ke "genap", dan "bahkan" kebetulan "turun", tetapi implementasinya salah dibulatkan "ke atas" (double tidak terpengaruh.) Untuk informasi selengkapnya dan detail implementasi, lihat microsoft/STL#2366.

Perubahan ini memengaruhi perilaku runtime dalam rentang kasus yang ditentukan:

Contoh

// 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");
}

Dalam versi sebelum Visual Studio 2022 versi 17.2:

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.

Dalam Visual Studio 2022 versi 17.2 dan yang lebih baru:

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__ memungkinkan __STDC__ tersedia untuk C

Standar C mengharuskan implementasi C yang sesuai mendefinisikan __STDC__ sebagai 1. Karena perilaku UCRT, yang tidak mengekspos fungsi POSIX ketika __STDC__ adalah 1, tidak dimungkinkan untuk menentukan makro ini untuk C secara default tanpa memperkenalkan perubahan mencolok ke versi bahasa yang stabil. Visual Studio 2022 versi 17.2 dan yang lebih baru menambahkan opsi /Zc:__STDC__ kesesuaian yang menentukan makro ini. Tidak ada versi negatif dari opsi ini. Saat ini, kami berencana untuk menggunakan opsi ini secara default untuk versi C pada waktu mendatang.

Perubahan ini adalah perubahan pemecah sumber. Ini berlaku ketika mode C11 atau C17 diaktifkan, /std:c11 atau /std:c17, bersama dengan /Zc:__STDC__.

Contoh

// 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__

*/

Peringatan untuk tanda kurung kurawal yang hilang

Peringatan C5246 melaporkan kurung kurawal yang hilang selama inisialisasi agregat subobjek. Sebelum Visual Studio 2022 versi 17.2, peringatan tidak menangani kasus anonim struct atau union.

Perubahan ini adalah perubahan pemecah sumber. Ini berlaku ketika peringatan off-by-default C5246 diaktifkan.

Contoh

Di Visual Studio 2022 versi 17.2 dan yang lebih baru, kode ini sekarang menyebabkan kesalahan:

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
*/

Untuk mengatasi masalah ini, tambahkan kurung kurawal ke penginisialisasi:

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

Peningkatan kesesuaian di Visual Studio 2022 versi 17.1

Visual Studio 2022 versi 17.1 berisi peningkatan kesesuaian berikut, perbaikan bug, dan perubahan perilaku dalam pengompilasi Microsoft C/C++.

Mendeteksi default pengambilan yang tidak terbentuk dalam ekspresi lambda nonlokal

Standar C++ hanya memungkinkan ekspresi lambda dalam cakupan blok memiliki capture-default. Di Visual Studio 2022 versi 17.1 dan yang lebih baru, kompilator mendeteksi kapan default pengambilan tidak diizinkan dalam ekspresi lambda nonlokal. Ini memancarkan peringatan tingkat 4 baru, C5253.

Perubahan ini adalah perubahan pemecah sumber. Ini berlaku dalam mode apa pun yang menggunakan prosesor lambda baru: /Zc:lambda, /std:c++20, atau /std:c++latest.

Contoh

Di Visual Studio 2022 versi 17.1 kode ini sekarang mengeluarkan kesalahan:

#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; };
//              ^

Untuk memperbaiki masalah ini, hapus default pengambilan:

#pragma warning(error:5253)

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

C4028 sekarang menjadi C4133 untuk operasi function-to-pointer

Sebelum Visual Studio 2022 versi 17.1, pengompilasi melaporkan pesan kesalahan yang salah pada perbandingan pointer-to-function tertentu dalam kode C. Pesan yang salah dilaporkan ketika Anda membandingkan dua pointer fungsi yang memiliki jumlah argumen yang sama tetapi jenis yang tidak kompatibel. Sekarang, kami mengeluarkan peringatan berbeda yang mengeluh tentang ketidakcocokan pointer-to-function daripada ketidakcocokan parameter fungsi.

Perubahan ini adalah perubahan pemecah sumber. Ini berlaku ketika kode dikompilasi sebagai C.

Contoh

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)'

Kesalahan pada nondependent static_assert

Di Visual Studio 2022 versi 17.1 dan yang lebih baru, jika ekspresi yang static_assert terkait dengan bukan ekspresi dependen, pengkompilasi mengevaluasi ekspresi saat diurai. Jika ekspresi mengevaluasi ke false, pengompilasi memancarkan kesalahan. Sebelumnya, jika static_assert berada dalam isi templat fungsi (atau dalam isi fungsi anggota templat kelas), pengompilasi tidak akan melakukan analisis ini.

Perubahan ini adalah perubahan pemecah sumber. Ini berlaku dalam mode apa pun yang menyiratkan /permissive- atau /Zc:static_assert. Perubahan perilaku ini dapat dinonaktifkan dengan menggunakan opsi pengompilasi /Zc:static_assert-.

Contoh

Di Visual Studio 2022 versi 17.1 dan yang lebih baru, kode ini sekarang menyebabkan kesalahan:

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

Untuk memperbaiki masalah ini, buat ekspresi menjadi dependen. Misalnya:

template<typename>
constexpr bool dependent_false = false;

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

Dengan perubahan ini, pengompilasi hanya memancarkan kesalahan jika templat fungsi f dibuat.

Peningkatan kesesuaian di Visual Studio 2022 versi 17.0

Visual Studio 2022 versi 17.0 berisi peningkatan kesesuaian berikut, perbaikan bug, dan perubahan perilaku dalam pengompilasi Microsoft C/C++.

Peringatan pada lebar bitfield untuk jenis enumerasi

Ketika mendeklarasikan instans jenis enumerasi sebagai bitfield, lebar bitfield harus mengakomodasi semua kemungkinan nilai enumerasi. Jika tidak, pengompilasi mengeluarkan pesan diagnostik. Pertimbangkan contoh ini: Pertimbangkan:

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

struct S {
  E e : 1;
};

Seorang programmer mungkin mengharapkan anggota kelas S::e dapat menyimpan salah satu nilai bernama enum secara eksplisit. Mengingat jumlah elemen enumerasi, itu tidak mungkin. Bitfield tidak dapat mencakup rentang nilai E yang disediakan secara eksplisit (secara konseptual, domain ).E Untuk mengatasi kekhawatiran bahwa lebar bitfield tidak cukup besar untuk domain enumerasi, peringatan baru (nonaktif secara default) ditambahkan ke MSVC:

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 };
                                     ^

Perilaku pengompilasi ini adalah perubahan pemecahan sumber dan biner yang memengaruhi semua mode /std dan /permissive.

Kesalahan pada perbandingan pointer yang diurutkan terhadap nullptr atau 0

Standar C++ secara tidak sengaja mengizinkan perbandingan pointer yang diurutkan terhadap nullptr atau 0. Misalnya:

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

Kertas WG21 N3478 menghilangkan pengawasan ini. Perubahan ini diimplementasikan dalam MSVC. Ketika contoh dikompilasi dengan menggunakan /permissive- (dan /diagnostics:caret), contoh tersebut memancarkan kesalahan berikut:

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

Perilaku pengompilasi ini adalah perubahan pemecahan sumber dan biner yang memengaruhi kode yang dikompilasi menggunakan /permissive- di semua /std mode.

Lihat juga

Kesesuaian bahasa Microsoft C/C++