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 member1
anggota . 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:
Berikut ini tersedia untuk semua versi bahasa C:
Pustaka Standar C++
Fitur C++23
formattable
,range_format
,format_kind
, danset_debug_format()
sebagai bagian dari Rentang Pemformatan P2286R8<mdspan>
per P0009R18 dan perubahan kata berikutnya yang diterapkan ke Standar C++23.format()
pointer per P2510R3.
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 long
atau 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 int
yang 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
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk