جستجو در تالارهای گفتگو
در حال نمایش نتایج برای برچسب های 'cpp23'.
2 نتیجه پیدا شد
-
با سلام و درود، پیرو مقالهٔ قبلی در رابطه با بخشی از نهاییسازیهای استاندارد ۲۳ در این مقاله قصد داریم در رابطه با استاندارد ۲۶ و نهاییسازیهای ۲۳ یک جمعبندی داشته باشیم که بسیار در شناخت و بهروز رسانی سریع از پیشرفت این زبان را به ما نشان میدهد. طبق جلسات اخیر از کمیتهٔ استانداردسازی، در اولین جلسه، کمیته بر اصلاح ویژگیهای C++23 متمرکز شد که عبارتند از: عملگرstatic operator[] ویژگی static constexpr در توابع constexpr محدودهٔ ایمن range-based در for تعامل std::print با سایر خروجی های کنسول رابط الگوی مونادیک برای std::expected خاصیتstatic_assert (false) و سایر ویژگیها در جلسهٔ دوم، کمیته بر روی توسعه ویژگیهای جدید برای C++26 کار کرد، از جمله: ویژگیهای std::get و std::tuple_size ماکروی #embed بدست آوردن std::stacktrace از استثناءها کرووتینهای (coroutines) پشتهای در ویژگیهای سیپلاسپلاس ۲۳ (static operator[]) تابستان گذشته، کمیته ویژگی static operator() را به استاندارد C++23 اضافه کرد و امکان تعریف operator[] را برای چندین آرگومان فراهم کرد. مرحلهٔ منطقی بعدی دادن فرصتهای برابر به این عملگرها بود، یعنی اضافه کردن توانایی نوشتنِ static operator[]. enum class Color { red, green, blue }; struct kEnumToStringViewBimap { static constexpr std::string_view operator[](Color color) noexcept { switch(color) { case Color::red: return "red"; case Color::green: return "green"; case Color::blue: return "blue"; } } static constexpr Color operator[](std::string_view color) noexcept { if (color == "red") { return Color::red; } else if (color == "green") { return Color::green; } else if (color == "blue") { return Color::blue; } } }; // ... assert(kEnumToStringViewBimap{}["red"] == Color::red); آیا این کد واقعاً کارآمد برای تبدیل رشته به enum است؟ ممکن است تعجب آور باشد، اما کد فوق در واقع بسیار کارآمد است. توسعهدهندگانِ کامپایلر از رویکردهای مشابهی استفاده میکنند و ما نیز تکنیک مشابهی را در چارچوب userver پیادهسازی کردهایم. ما یک کلاس جداگانه به نام utils::TrivialBiMap با رابطکاربری راحتتر ایجاد کردهایم. constexpr utils::TrivialBiMap kEnumToStringViewBimap = [](auto selector) { return selector() .Case("red", Color::red) .Case("green", Color::green) .Case("blue", Color::blue); }; راندمان بالا به لطف ویژگی کامپایلرهای بهینهسازی مدرن به دست میآید (اما هنگام نوشتن یک راه حل کلی باید بسیار مراقب بود). پیشنهاد در سند P2589R1 تمام جزئیات لازم را شرح میدهد. ویژگی static constexpr در توابع constexpr استاندارد C++23 عملکرد خود را با افزودن constexpr به_chars/from_chars گسترش داده است. اما برخی از اجرا کنندهگان با مشکل مواجه شدند. چندین کتابخانهٔ استاندارد حاوی آرایههای ثابتی برای تبدیل سریع string<>number بودند که به عنوان متغیرهای ثابت در توابع اعلام شدند. متأسفانه، این مانع استفاده از آنها در توابع constexpr شد. این مسئله قابل حل است، اما راه حل ها واقعاً ناشیانه به نظر میرسید. در نهایت، کمیته با اجازه دادن به استفاده از متغیرهای static constexpr در توابع constexpr، همانطور که در سند P2647R1 مشخص شد که مشکل را حل کرده است. یک پیشرفت کوچک، اما خوشایند. محدودهٔ ایمن range-based در حلقهٔ for این احتمالاً هیجان انگیزترین خبری است که از دو نشست جلسهٔ استانداردسازیهای گذشته منتشر میشود! در مورد آن، اجازه دهید با یک معمای سرگرم کننده شروع کنیم: آیا میتوانید اشکال موجود در کد را شناسایی کنید؟ class SomeData { public: // ... const std::vector<int>& Get() const { return data_; } private: std::vector<int> data_; }; SomeData Foo(); int main() { for (int v: Foo().Get()) { std::cout << v << ','; } } هرچند پاسخ آن در اینجا آمده است: The Foo() function returns a temporary object, and when the Get() method is called on this object, it returns a reference to the data inside the temporary object. The range-based for loop is then transformed into a code close to this one: auto && __range = Foo().Get() ; for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin) { int v = *__begin; std::cout << v << ','; } Here, the first string is equivalent to this: const std::vector<int>& __range = Foo().Get() ; The result is a dangling reference. حلقههای مبتنی بر محدوده (Range-based for) شامل فرآیندهای زیربنایی زیادی هستند و در نتیجه، این نوع باگها ممکن است همیشه آشکار نباشند. در حالی که میتوان این مشکلات را از طریق آزمایشهای مربوط به sanitizersها به طور مؤثر تشخیص داد، پروژههای نوین معمولاً آنها را بهعنوان روش استاندارد شامل میشوند (پروژههای مطرحی مانند Yandex، از این قاعده مستثنی نیستند). با این حال، ایدهآل است که در صورت امکان از چنین اشکالاتی به طور کامل اجتناب کنید. در RG21، ما اولین تلاش خود را برای بهبود این وضعیت چهار سال پیش با سند D0890R0 انجام دادیم. متأسفانه، این روند در مرحله بحث متوقف شد. خوشبختانه، Nicolai Josuttis ابتکار عمل را انتخاب کرد و در C++23، کدهای مشابه دیگر مرجع معلق (dangling reference) ایجاد نمیکنند. تمام اشیایی که در سمت راست : در یک حلقه for مبتنی بر محدوده (ranges) ایجاد میشوند، اکنون فقط هنگام خروج از حلقه از بین میروند. برای جزئیات فنیِ بیشتر، لطفاً به سند P2718R0 مراجعه کنید. ویژگی std::print در C++23، یک بهروزرسانی کوچک اما قابل توجه برایstd::print وجود دارد: خروجی آن برای «همگامسازی» با سایر خروجیهای داده تنظیم شده است. در حالی که بعید است کتابخانههای استاندارد در سیستمعاملهای نوین تغییرات قابل توجهی را تجربه کنند، استاندارد بهروز شده اکنون تضمین میکند که پیامها به ترتیبی که در کد منبع ظاهر میشوند به کنسول خروجی ساطع میشوند: printf("first"); std::print("second"); رابط الگوی مونادیک برای std::expected یک ویژگی نسبتاً مهم در آخرین لحظه به C++23 اضافه شد: یک رابط مونادیک برای std::expected، مشابه رابط مونادیک که قبلاً برای std::optional موجود بود، اضافه شده است. using std::chrono::system_clock; std::expected<system_clock, std::string> from_iso_str(std::string_view time); std::expected<formats::bson::Timestamp, std::string> to_bson(system_clock time); std::expected<int, std::string> insert_into_db(formats::bson::Timestamp time); // Somewhere in the application code... from_iso_str(input_data) .and_then(&to_bson) .and_then(&insert_into_db) // Throws “Exception” if any of the previous steps resulted in an error .transform_error([](std::string_view error) -> std::string_view { throw Exception(error); }) ; میتوانید شرح کاملی از تمام رابطهای مونادیک برای std::expected را در سند P2505R5 بیابید. خاصیتstatic_assert (false) و سایر ویژگیها علاوه بر تغییرات قابل توجهی که در بالا ذکر شد، تعداد زیادی بازنگری برای حذف لبههای ناهموار جزئی و بهبود توسعه روزمره انجام شده است. به عنوان مثال، فرمتکنندهها برای std::thread::id و std::stacktrace (P2693 سند) تا بتوان از آنها با std::print و std::format استفاده کرد. به ویژه std::start_lifetime_a بررسیهای زمان کامپایل اضافی را در سند P2679 دریافت کرده است. قابل توجه است که خاصیت static_assert(false) در توابع الگو (template function) دیگر بدون نمونهسازی تابع فعال نمیشود، به این معنی که کدی مانند زیر فقط در صورت ارسال نوع داده اشتباه، عیبیابی را کامپایل و صادر میکند: template <class T> int foo() { if constexpr (std::is_same_v<T, int>) { return 42; } else if constexpr (std::is_same_v<T, float>) { return 24; } else { static_assert(false, "T should be an int or a float"); } } علاوه بر تغییراتی که قبلاً ذکر شد، بهبودهای بیشماری در خاصیت (ranges) از C++23 انجام شده است. مهمترین آنها گنجاندن std::views::enumerate در سند P2164 است: #include <ranges> constexpr std::string_view days[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", }; for(const auto & [index, value]: std::views::enumerate(days)) { print("{} {} \n", index, value); } ویژگیهای سیپلاسپلاس ۲۶ ویژگیهای std::get و std::tuple_size برای (aggregates) تجمیع یک ایدهٔ جدید و هیجان انگیز برای بهبود ++C وجود دارد که در حال حاضر به طور فعال در Yandex Go و چارچوب userver استفاده میشود و به لطف Boost.PFR برای هر کسی که آن را میخواهد در دسترس است. اگر در حال نوشتن یک کتابخانهٔ مبتنی بر الگو (template) و عمومی هستید، به احتمال زیاد باید از std::tuple و std::pair استفاده کنید. با این حال، برخی از مشکلات در این نوع وجود دارد. اولاً، آنها خواندن و درک کد را دشوار میکنند زیرا ورودیهای نامِ واضحی ندارند، و تشخیص معنای چیزی مانندstd::get<0>(tuple) میتواند چالش برانگیز باشد. علاوه بر این، کاربران کتابخانهٔ شما ممکن است نخواهند مستقیماً با این انواع کار کنند و درست قبل از فراخوانیِ روشهای شما، اشیاءای از این نوع ایجاد میکنند که به دلیل کپی کردن دادهها میتواند ناکارآمد باشد. ثانیاً، std::tuple و std::pair بیاهمیت بودن انواعی را که ذخیره می کنند، «تبلیغ نمی کنند». در نتیجه، هنگام ارسال و برگرداندن std::tuple و std::pair از توابع، کامپایلر ممکن است کدی را با کارآیی پایینتر تولید کند. با این حال، aggregates (تجمیعها) - ساختارهایی (struct) با میدانهای عمومی و بدون عملکرد خاص - عاری از اشکالات ذکر شده هستند. ایدهای که پشت سند P2141R0 وجود دارد، این است که با کار کردن std::get و std::tuple_size آنها، امکان استفاده از تجمیعها در کدهای عمومی را فراهم میکند. این به کاربران امکان میدهد تا ساختارهای خود را مستقیماً بدون کپی برداری غیر ضروری به کتابخانهٔ عمومی شما منتقل کنند. این ایده به خوبی توسط کمیته مورد استقبال قرار گرفت، و ما در آینده روی آزمایش و رسیدگی به هرگونه لبهٔ ناهموار و بالقوه در این زمینه کار خواهیم کرد. ماکروی #embed در حال حاضر، توسعهٔ فعالی روی یک استاندارد زبان C جدید (یک استاندارد بدون کلاس، بدون ++) وجود دارد که شامل بسیاری از ویژگیهای مفیدی است که مدتهاست در ++C وجود داشته است (مانند: nullptr، auto، constexpr، static_assert، thread_local، [[noreturn]).])، و همچنین ویژگیهای کاملاً جدید برای ++C. خبر خوب این است که برخی از ویژگیهای جدید از استاندارد جدید C به C++26 منتقل میشوند. یکی از این موارد جدید، #embed است - یک دستورالعمل پیش پردازنده برای جایگزینی محتویات یک فایل به عنوان یک آرایه در زمان کامپایل: const std::byte icon_display_data[] = { #embed "art.png" }; شرح کامل این ایده در سند P1967 موجود است. بدست آوردن std::stacktrace از استثناءها در اینجا، ایدهٔ سند P2370 در WG21 با یک شکست غیرمنتظره روبرو شده است. توانایی به دست آوردن ردیابی پشته از یک استثناء در اکثر زبانهای برنامهنویسی وجود دارد. این ویژگی فوقالعاده مفید است و به جای پیامهای خطای غیر اطلاعاتی مانند Caught exception: map::at تشخیصهای آموزندهتر و قابل فهمتر را امکانپذیر میکند که نمونه مثال آن به صورت زیر است: Caught exception: map::at, trace: 0# get_data_from_config(std::string_view) at /home/axolm/basic.cpp:600 1# bar(std::string_view) at /home/axolm/basic.cpp:6 2# main at /home/axolm/basic.cpp:17 هنگامی که در محیط یکپارچه سازی پیوسته (CI) استفاده میشود، این ویژگی میتواند فوقالعاده مفید باشد. این به شما امکان میدهد تا به سرعت مسائل را در آزمون شناسایی کنید و از دردسر بازتولید مشکل به صورت محلی اجتناب کنید، که ممکن است همیشه امکانپذیر نباشد. متأسفانه کمیتهٔ بینالمللی به طور کامل از این ایده استقبال نکرد. اما تیم توسعه نگرانیها را بررسی میکند و روی اصلاح این ایده کار خواهد کرد تا بتواند حمایت بیشتری را کسب کند. کسانی که معمولاً میپرسند چه تفاوتی بین زبانهای دیگر و استانداردهای سی++ وجود دارد، در اینجا میتوانند به این موضوع دقت کنند که زبانی مانند سیپلاسپلاس دارای کمیتهٔ استانداردسازی بینالمللی است و هر تغییری باید قابل توجیه باشد. کروتینهای (coroutines) پشته سرانجام، پس از سالها کار، استاندارد سیپلاسدلاس به افزودن پشتیبانی اولیه برای برنامههای پشتهای در C++26 نزدیک شده است (به سند P0876 مراجعه کنید). ارزش آن را دارد که بیشتر در مورد روالهای پشتهای یا بدون پشته بررسی کنیم. برنامههای بدون پشته به پشتیبانی کامپایلر نیاز دارند و نمیتوانند به تنهایی به عنوان یک کتابخانه پیادهسازی شوند. از سوی دیگر، کروتینهای پشتهای را میتوان به تنهایی پیادهسازی کرد - برای مثال، با Boost.Context. در حالتهای قبلی، تخصیص حافظه کارآمدتر، بهینهسازی بالقوه بهتر کامپایلر و توانایی تخریب سریع آنها را ارائه میدهد. آنها همچنین در حال حاضر در C++20 در دسترس هستند. ادغام نمونههای اخیر در پروژههای موجود بسیار آسانتر است، زیرا نیازی به بازنویسی کامل در یک اصطلاح جدید مانند برنامههای بدون پشته ندارند. در واقع، آنها جزئیات پیادهسازی را به طور کامل از کاربر مخفی میکنند و آنها را قادر میسازند تا کد خطی سادهای را که در لایههای زیرینِ ناهمزمانی هستند بنویسند. بدون پشته (Stackless) auto data = co_await socket.receive(); process(data); co_await socket.send(data); co_return; // requires function to return a special data type پشتهای (Stackfull) auto data = socket.receive(); process(data); socket.send(data); سند P0876 قبلاً در زیرگروه اصلی قرار داشته است. پس از بحث و گفتگو، تصمیم گرفته شد که مهاجرت این گونه برنامهها (coroutines) بین رشتههای اجرایی ممنوع شود. دلیل اصلی این ممنوعیت این است که کامپایلرها دسترسی به TLS را بهینه کرده و مقادیر متغیرهای TLS را در حافظه پنهان ذخیره میکنند: thread_local int i = 0; // ... ++i; foo(); // Stackful coroutines can switch execution threads assert(i > 0); // The compiler saved the address in a register; we’re working with the TLS of another thread جمعبندی در نهایت استاندارد C++23 رسماً به مقامات بالاتر از کمیتهٔ ISO ارسال شده است و به زودی به عنوان یک استاندارد کامل منتشر خواهد شد. در همین حال، توسعه C++26 در نوسان کامل است و چشماندازهای هیجانانگیزی برای خاصیتهای متنوع وجود دارد. اگر ایدههای نوآورانهای برای بهبود ++C دارید، با خیال راحت آنها را به اشتراک بگذارید. یا - حتی بهتر - ارسال یک پیشنهاد را در نظر بگیرید.
-
نهاییسازی ویژگیهای استاندارد ۲۳ و خلاصهای از جلسهٔ استانداردسازی WG21
کامبیز اسدزاده نوشته وبلاگ را ارسال کرد در فناوری
با سلام، با توجه به گزارش آنتونی پولوخین که یکی از اعضای کمیتهٔ استانداردسازی WG21 (سازمانی که توسعهٔ زبان برنامهنویسی سیپلاسپلاس را کنترل میکند). این کمیته سه بار در هر سال، هر بار در یک شهر جدید در سراسر جهان جلسه برگزار میکند. در طول این جلسات، پیشنهاداتی برای تغییر در زبان در نظر گرفته میشود. همچنین به توسعهدهندههای محلی سی++ کمک میکنند تا پیشنهادات خود را ارائه کنند. خلاصهای از جلسهٔ ماه جولای با هدف نهایی شدن استاندارد ۲۳ که نشان میهد پیشرفت بزرگی به عنوان ویژگیهای جدید استاندارد ۲۳ وجود دارد ارائه شده است: فهرست برخی از ویژگیها به صورت زیر آمدهاست: std:mdspan std:flat_map std:flat_set freestanding std:print("Hello {}", "world") formatted ranges output constexpr for bitset, to_chars/from_chars std::string::substr() && import std; std::start_lifetime_as static operator() [[assume(x > 0)]] 16- and 128-bit floats std::generator و البته ویژگیهای بسیار بیشتر از این. ویژگی std::mdspan از زمان اتخاذ عملگر opertator[] چند بعدی در آخرین جلسه، معرفیstd::mdspan به عنوان یک ویژگی سادهتر مطرح شده است و نتیجهٔ یک آرایهٔ چند بعدی غیر مالک به صورت زیر است: using Extents = std::extents<std::size_t, 42,="" 32,="" 64="">; double buffer[ Extents::static_extent(0) * Extents::static_extent(1) * Extents::static_extent(2) ]; std::mdspan<double, Extents=""> A{ buffer }; assert( 3 == A.rank() ); assert( 42 == A.extent(0) ); assert( 32 == A.extent(1) ); assert( 64 == A.extent(2) ); assert( A.size() == A.extent(0) * A.extent(1) * A.extent(2) ); assert( &A(0,0,0) == buffer ); این ویژگی حتی میتواند با سایر زبانهای برنامهنویسی خارج از جعبه کار کند. به عنوان مثال، در پارامتر الگوی سوم خود، std::mdspan میتواند یکی از چندین کلاس طرح بندی از پیش تعریف شده را بگیرد: نوعstd::layout_right: سبک چیدمان برای C یا ++C، سطرها دارای شاخص صفر هستند. نوعstd::layout_left: سبک چیدمان برای Fortran یا Matlab، ستونها دارای شاخص صفر هستند. شما می توانید تمام جزئیات را در سند P0009 بیابید. نویسندگان قول دادهاند که در آینده نزدیک نمونههای زیادی از std:mdspan جدید ارائه کنند. ویژگی std::flat_map و std::flat_set نگهدارندههای شگفتانگیز flat_* از کتابخانهٔ بوست، دیگر در استاندارد اصلی سی++ در دسترس هستند. این خاصیتها در کار با دادههای کم بسیار پرکاربرد هستند. در زیر ساختها، ظروف flat دادهها را در یک آرایه مرتب شده ذخیرهسازی میکنند که به طور قابل توجهی تخصیص حافظهٔ پویا را کاهش داده و موقعیت دادهها را بهبود میبخشد. علیرغم پیچیدگی جستجوی O(log N) و پیچیدگی درجO(N) در بدترین حالت، ظروف مسطح هنگام کار با مقدار کمی از عناصر بهتر از std:unordered_map عمل میکنند. در واقع، در طی فرآیند استانداردسازی، ظروف flat_* به عنوان آداپتور ساخته شدهاند. به این ترتیب، برنامهنویسان میتوانند از نگهدارندههای خود برای پیادهسازی اساسی استفاده کنند: template <std::size_t N> using MyMap = std::flat_map< std::string, int, std::less<>, mylib::stack_vector<std::string, N>, mylib::stack_vector<int, N> >; static MyMap<3> kCoolestyMapping = { {"C", -200}, {"userver", -273}, {"C++", -273}, }; assert( kCoolestyMapping["userver"] == -273 ); const auto& keys = kCoolestyMapping.keys(); // Inspired by Python :) assert( keys.back() == "userver" ); یک نکتهٔ جالب این است که استاندارد STL برخلاف پیادهسازی Boost، کلیدها و مقادیر را در نگهدارندهها جداگانه ذخیره میکند. این مکانِ کلیدیِ بهبود یافته، جستجوی ظرفِ flat را سریعتر میکند. رابط کاملstd::flat_set در سند P1222 توضیح داده شده است، در حالی که شرح رابط std:flat_map در سند P0429 موجود است. مستقل (Freestanding) استاندارد ++C میگوید که امکان پیادهسازی کتابخانهٔ استاندارد به صورت میزبان (hosted) یا مستقل (freestanding) وجود دارد. پیادهسازی میزبان نیاز به پشتیبانی سیستمعامل دارد و باید تمام روشها و کلاسها را از کتابخانهٔ استاندارد پیادهسازی کند. مستقل (freestanding) میتواند بدون سیستمعامل کار کند، سختافزار مهم نیست، و برخی از کلاسها و توابع را شامل نمیشود. تا همین اواخر، هیچ توضیحی برای ایستادن آزاد وجود نداشت و سازندگان سختافزارهای مختلف بخشهای مختلفی از کتابخانهٔ استاندارد را ارائه میکردند. این کارِ پورت کردن کد را سختتر کرد و محبوبیت ++C را در محیطهای تعبیهشده (امبدها) تضعیف کرد. بنابراین، زمان تغییر آن فرا رسیده است! سند P1642 مشخص کرده است که کدام بخش از کتابخانهٔ استاندارد برای freestanding اجباری است. ویژگی std::print روشهایی از کتابخانهء محبوب fmt در C++20 اضافه شد. این کتابخانه آنقدر راحت و سریع بود که برنامهنویسان شروع به استفاده از آن کرده و تقریباً در همهجای کد خود به کار بردهاند، از جمله برای خروجی قالببندی شده: std::cout << std::format(“Hello, {}! You have {} mails”, username, email_count); اما کدی مانند آن به دلایل زیر کامل نیست: تخصیص پویا اضافی. نیاز به std::cout جهت قالببندی خطوط از قبل قالب بندی شده. عدم پشتیبانی از یونیکد. کدی که اندازهٔ فایل باینری حاصل را افزایش میدهد. ظاهری نه چندان جذاب. بنابراین، تمام این مشکلات با اضافه کردن متدهایstd::print حل شد: std::print(“سلام, {}! به جامعهٔ {} خوش آمدید!”, name, community); میتوانید جزئیات، معیارها و گزینههای استفاده ازstd::print باFILE* و استریمها را در سند P2093 بیابید. خروجی قالببندی شده محدودههای مقدار به لطف سند P2286 و، std::format (و std::print) اکنون میتوانند محدودههایی از مقادیر را بدون در نظر گرفتن اینکه در یک ظرف هستند یا توسط std::ranges::views::* ارائه شدهاند خروجی بگیرند. std::print("{}", std::vector<int>{1, 2, 3}); // Output: [1, 2, 3] std::print("{}", std::set<int>{1, 2, 3}); // Output: {1, 2, 3} std::print("{}", std::pair{42, 16}); // Output: (42, 16) std::vector v1 = {1, 2}; std::vector v2 = {'a', 'b', 'c'}; auto val = std::format("{}", std::views::zip(v1, v2)); // [(1, 'a'), (2, 'b')] ویژگی constexpr اخبار تجزیه و تحلیل عالی برای توسعهدهندگانی که با کتابخانههای مختلف کار میکنند وجود دارد: خاصیتهایstd::to_chars/std::from_chars اکنون میتوانند در مرحله کامپایل برای تبدیل مقادیر صحیح از متن به باینری استفاده شوند. این نیز باید هنگام توسعه DSL مفید باشد. به نظر میرسد توسعهدهندههای روسی Yandex Go (به نقل از عضو کمیته) قصد دارند از آن در چارچوب کاربر برای بررسی پرس و جوهای SQL در مرحله کامپایل استفاده کنند. گزینهٔ std::bitset نیز تبدیل به constexpr شده است، بنابراین کار با بیتها در مرحلهٔ کامپایل اکنون بسیار آسانتر از قبل است. دانیل گوچاروف روی std::bitset در سند P2417 کار کرد و الکساندر کارائف در سند std::to_chars/std::from_chars P2291 به او پیوست. با تشکر فراوان از آنها برای این کار خوب انجام شده! ویژگی import std; با توجه به اینکه، اولین ماژول کامل(تمامعیار) به کتابخانهٔ استاندارد (STL) اضافه شد. اکنون میتوان کل کتابخانه را با یک خط بر سند وارد کرد: import std;. اگر کل ماژول کتابخانهٔ استاندارد به جای گنجاندن فایلهای هدر وارد شود، ساختها میتوانند تا ۱۱ برابر (گاهی اوقات حتی ۴۰ بار!) سریعتر شوند. میتوانید بنچمارک ها را در P2412 مشاهده کنید. اگر به ترکیب ++C و C و همچنین استفاده از توابع C از فضای نام جهانی عادت دارید، ماژول std.compat برای شما مناسب است. وارد کردن آن همهٔ توابع فایلهای سرآیند C مانند ::fopen و ::isblank و همچنین محتویات کتابخانهٔ استاندارد را در اختیار شما قرار میدهد. با وجود همهٔ اینها، سند P2465 که ماژولهای جدید را پوشش میدهد، در واقع آنقدرها هم طولانی نیست. ویژگی std::start_lifetime_as تیمور داملر و ریچارد اسمیت یک هدیهٔ فوقالعاده برای همهٔ توسعهدهندگانی که روی برنامههای تعبیه شده (امبد) و پربار کار میکنند گرد هم آوردهاند. اکنون تنها چیزی که برای کار کردن همه چیز نیاز دارید این است: struct ProtocolHeader { unsigned char version; unsigned char msg_type; unsigned char chunks_count; }; void ReceiveData(std::span<std::byte> data_from_net) { if (data_from_net.size() < sizeof(ProtocolHeader)) throw SomeException(); const auto* header = std::start_lifetime_as<ProtocolHeader>( data_from_net.data() ); switch (header->type) {> // ... } } به عبارت دیگر، میتوانید بافرهای مختلف را به ساختارها تبدیل کنید و با آنها بدون reinterpret_cast، کپی کردن دادهها یا خطر عملکرد برنامهتان کار کنید. همه چیز در سند P2590 شرح و مستند شده است. ویژگیهای شناورهای (اعشاری) 16 و 128 بیتی استاندارد ++C اکنون شامل std::float16_t، std::bfloat16_t، std::float128_t و نام مستعار برای اعداد موجود با ممیز شناور است: std::float32_t، std::float16_t. شناورهای 16 بیتی در هنگام کار با کارتهای ویدئویی یا یادگیری ماشین کمک میکنند. به عنوان مثال، float16.h میتواند از انواع جدید شناور کوتاه بهرهمند شود. شناورهای 128 بیتی برای محاسبات علمی شامل اعداد بزرگ بهترین هستند. سندِ P1467 ماکروها را برای بررسی پشتیبانی کامپایلر برای اعداد جدید توصیف میکند، و حتی خاصیتِ stdfloat.properties، در جدول مقایسه با توصیف اندازههای مانتیس و توان در بیتها وجود دارد. ویژگی std::generator زمانی که کروتینها در استاندارد C++20 پذیرفته شدند، ایده این بود که میتوان از آنها برای ایجاد «مولد» استفاده کرد: توابعی که وضعیت خود را بین تماسها به خاطر میآورد و مقادیر جدید را بر اساس آن حالت برمیگرداند. در استاندارد C++23 با اشاره به، std::generator به عنوان یک کلاس جدید یاد میشود که به شما امکان میدهد به راحتی ژنراتورهای خود را ایجاد کنید: std::generator<int> fib() { auto a = 0, b = 1; while (true) { co_yield std::exchange(a, std::exchange(b, a + b)); } } int answer_to_the_universe() { auto rng = fib() | std::views::drop(6) | std::views::take(3); return std::ranges::fold_left(std::move(rng), 0, std::plus{}); } در مثال فوق میتوانید ببینید که ژنراتورها با std::ranges چقدر خوب کار میکنند. std::generator کارآمد و ایمن است. کدی که به نظر میرسد یک پیوند معلق ایجاد میکند در واقع کاملاً معتبر است و هیچ مشکلی ایجاد نمیکند: std::generator<const std::string&=""> greeter() { std::size_t i = 0; while (true) { co_await promise::yield_value("hello" + std::to_string(++i)); // Everything is ok! } } میتوانید مثالها و توضیحاتی دربارهٔ نحوه کارکرد و استدلال پشت این رابط را در سند P2502 بیابید. سورپرایزهای دلپذیر کلاس string استاندارد برای متد substr() برای ارجاعات rvalue یک بازنگری اساسی (بهبود) دریافت کرده است: std::string::substr() &&. مانند مثال زیر: std::string StripSchema(std::string url) { if (url.starts_with("http://")) return std::move(url).substr(5); if (url.starts_with("https://")) return std::move(url).substr(6); return url; } این روش اکنون بدون تخصیص پویا اضافی کار میکند. اطلاعات بیشتر را میتوانید در سند P2438 بیابید. به لطف سند P1169، اکنون میتوانیدoperator() را ثابت اعلام کنید، که برای ایجاد CPO برای محدودهها در کتابخانه استاندارد عالی است: namespace detail { struct begin_cpo { template <typename T> requires is_array_v<remove_reference_t<T>> || member_begin<T> || adl_begin<T> static auto operator()(T&& val); }; void begin() = delete; // poison pill } // namespace detail namespace ranges { inline constexpr detail::begin_cpo begin{}; // ranges::begin(container) } // namespace ranges علاوه بر std::start_lifetime_as، تیمور داملر یک راهنمایی عالی برای بهینهساز ارائه کرد[[assume (x > 0)]]. اکنون میتوانید در مورد مقادیر احتمالی اعداد و سایر متغیرهای ثابت به کامپایلر نکاتی بدهید. برخی از مثالها و معیارها در سند P1774 کاهش پنج برابری در تعداد دستورالعملهای اسمبلی را نشان میدهند. این استاندارد همچنین دارای بسیاری از ویرایشهای جزئی، رفع اشکال و پیشرفتها بوده است، در اینجا منظور استاندارد ۲۳ است. در برخی مکانها، از سازندههای حرکتی (move constructors) به جای سازندههای کپی (copy constructors) استفاده شد (P2266). خوشبختانه برای توسعهدهندگان درایور، برخی از عملیات فرار دیگر منسوخ نمیشوند (P2327 با رفع اشکال در C++20). عملگر<=> کدهای قدیمی را کمتر میشکند (P2468)، کاراکترهای یونیکد اکنون میتوانند با نام استفاده شوند (P2071)، و کامپایلرها عموماً برای پشتیبانی از یونیکد (P2295) مورد نیاز هستند. الگوریتمهای جدید برای محدودهها (ranges::contains P2302, views::as_rvalue P2446, views::repeat P2474, views::stride P1899, و ranges::fold P2322) و std::format_string برای بررسیهای زمان کامپایل اضافه شد. std::format (P2508) و ماکروی #warning در (P2437). محدودهها (Ranges) یاد گرفتاند که چگونه با انواع فقط حرکت کار کنند (P2494). و در نهایت std::forward_like برای ارسال متغیرها بر اساس نوع متغیر دیگری اضافه شد (P2445). برای مدت طولانی، به نظر میرسید مهمترین نوآوری C++23 اضافه کردن std::stacktrace از RG21 بود، اگرچه در آخرین جلسه ویژگیهای مورد انتظار بسیاری اضافه شد. نوآوریهایی برای توسعهدهندگان تعبیه شده، شیمیدانان/فیزیکدانان/ریاضیدانان/...، توسعهدهندگان کتابخانههای یادگیری ماشین، و حتی توسعهدهندگانی که روی برنامههای کاربردی با بار بالا کار میکنند، وجود دارد.-
- استاندارد
- سیپلاسپلاس
- (و 4 مورد دیگر)