رفتن به مطلب
مرجع رسمی سی‌پلاس‌پلاس ایران
کامبیز اسدزاده

اگر به دنبال یادگیری ویژگی‌های جدید از استاندارد سی++ هستید، این مقاله را به شما توصیه می‌کنم. در این مقاله من قصد دارم به ویژگی‌های حذف شده، اضافه شده، بهبود‌یافته و در حال توسعه از استاندارد‌های ۱۱ تا به بعد اشاره کنم. به خصوص استاندارد ۲۰ یا همان 2a هدف بعدی من است.

پیغام توسط کامبیز اسدزاده افزوده شد

امتیاز دادن به این موضوع:

پست های پیشنهاد شده

جزئیات در ۱۱ ++C و برخی بهبود‌ها در ویرایش ۱۷

جدا کننده رقم استاندارد ۱۱

تا قبل از استاندارد ۱۴ شما مجبور بودید تعداد رقم‌ها و یا صفر‌ها را بشمارید. از استاندارد ۱۴ به بعد دیگر نیازی به این کار نیست. این کار در زمان محاسبهٔ آدرس در کلمه، مرز‌های رقمی یا نیم کاراکتر‌ها مفید خواهد بود. در واقع با گروه‌بندی ارقام کد شما رسا‌تر خواهد شد.

int no = 1'000'000;
long addr = 0xA000'EFFF;
uint32_t binary = 0b0001'0010'0111'1111;

تعریف نام مستعار (Type aliases) استاندارد ۱۱

از لحاظ معنایی مشابه typedef است، هرچند نام‌های مستعار تعریف شده به این شیوه ساده‌تر بوده و تحت انواع الگو‌ها سازگار‌تر هستند. به مثال‌های زیر توجه کنید:

template <typename T>
using dynamicArray = std::vector<T>;
dynamicArray<int> nums; // equivalent to std::vector<int>
using func_ptr = int (*)(int);

و یا اگر بخواهید نام مستعاری از یک نوع std::map با کلید و مقدار از نوع رشته تعریف کنید، آنگاه به صورت زیر خواهد بود:

using mapString  = std::map<std::string, std::string>;

این روش برای موارد متنوعی مورد استفاده قرار که قبل و بعد از وجود آن را در مثال زیر می‌بینیم:

// C++11
using counter = long;

// C++03 equivalent:
// typedef long counter;

// C++11
using fmtfl = std::ios_base::fmtflags;

// C++03 equivalent:
// typedef std::ios_base::fmtflags fmtfl;

fmtfl fl_orig = std::cout.flags();
fmtfl fl_hex = (fl_orig & ~std::cout.basefield) | std::cout.showbase | std::cout.hex;
// ...
std::cout.flags(fl_hex);

// C++11
using func = void(*)(int);

// C++03 equivalent:
// typedef void (*func)(int);

// func can be assigned to a function pointer value
void actual_function(int arg) { /* some code */ }
func fptr = &actual_function;

template<typename T> using ptr = T*;

// the name 'ptr<T>' is now an alias for pointer to T
ptr<int> ptr_int;

الفاظ رشته‌ای تعریف شده توسط کاربر (User-defined literals) استاندارد ۱۱

  • در مواقع نیاز شما مجبورید با اصطلاحات واضحی مثل MB, KB, GB یا km، cm و یا واحد‌های دیگری جهت تبدیلات در زمان اجرا کار‌ی انجام دهید. اکنون به عنوان کاربر می‌توانید اصلاح مورد نیاز خود را همانند انواع pt (انواع ابتدائی) دیگر انجام دهید.
  • این شیوه برای واحد‌ها و اندازه‌گیری بسیار مناسب است.
  • اضافه کردن constexpr اثر هزینهٔ صفر از کارایی را در زمان اجرا فراهم می‌کند.
using ull = unsigned long long;

constexpr ull operator"" _KB(ull no)
{
    return no * 1024;
}
constexpr ull operator"" _MB(ull no)
{
    return no * (1024_KB);
}

int main()
{
  
  std::cout << 1_KB << std::endl;
  std::cout << 1_MB << std::endl;
  
  return 0;
}

ویژگی مقداردهی لیست اولیه (std::initializer_list) استاندارد ۱۱

std::pair<int, int> p = {1, 2};
std::tuple<int, int> t = {1, 2};
std::vector<int> v = {1, 2, 3, 4, 5};
std::set<int> s = {1, 2, 3, 4, 5};
std::list<int> l = {1, 2, 3, 4, 5};
std::deque<int> d = {1, 2, 3, 4, 5};
std::array<int, 5> a = {1, 2, 3, 4, 5};

این شیوه مشابه آرایه‌ها به سبک C مقادیر را مستقیماً با لیست مقدار دهندهٔ اولیه «std::initializer_list» اختصاص می‌دهد. همچنین به لطف استاندارد ۱۱ این مورد در مورد نگه‌دارنده‌های تو در تو هم صدق می‌کند.

 

ویژگی auto و decltype استاندارد ۱۱، بهبود و اضافات در استاندارد ۲۰

  • متغیر‌های تعریف شده به وسیلهٔ کلمهٔ کلیدی auto بر اساس نوع مقدار توسط کامپایلر استنباط می‌شوند.
  • متغیر‌های تعرف شده به کمک کلمهٔ کلیدی decltype بر اساس بررسی موجودیت یا نوع و مقادیر عبارت تعیین می‌شوند.
  • این ویژگی‌ها به شدت برای خواندن، به ویژه انواع پیچیده مفید است.
auto a = 3.14; // double

اجازه دهید یک مثال با ترکیب auto و decltype داشته باشیم.

به عنوان مثال، توابع می‌توانند به وسیلهٔ کلمهٔ کلیدی auto نیز نوع بازگشتی خود را استنباط کنند. در استاندارد ۱۱ نوع بازگشتی باید به طور صریح یا با استفاده از نوع decltype رمزگشایی شود، به مثال‌های عادی و الگو (template) مانند زیر توجه کنید:

auto getResult(std::string var) -> decltype (var) {
  return var;
}
template <typename X, typename Y>
auto add(X x, Y y) -> decltype(x + y)
{
    return x + y;
}
add(1, 2);     // == 3
add(1, 2.0);   // == 3.0
add(1.5, 1.5); // == 3.0

ویژگی Range-based for-loops استاندارد ۱۱ به علاوهٔ اضافات و بهبود‌ها در استاندارد ۱۷ و ۲۰

یک نحوِ شیرین برای تکرار عناصر در یک نگه‌دارنده یا ظرف (container)

std::vector<int> v = {0, 1, 2, 3, 4, 5};
for (const int& i : v) // access by const reference
  std::cout << i << ' ';
  std::cout << '\n';

برای بررسی برخی از ویژگی‌های مرتبط با این موضوع به مقالات زیر مراجعه کنید:

 

اشاره‌گر‌های هوشمند استاندارد ۱۱، بهبود‌ها در استاندارد ۱۷

استاندارد ۱۱ با خود اشاره‌گر‌های هوشمند را معرفی کرده است مانند std::unique_ptr، std::shared_ptr و std::weak_ptr که سپس std::auto_ptr در استاندارد ۱۷ به عنوان منسوخ شده معرفی و حذف شده است.

std::unique_ptr<int> p = std::make_unique<int>(128);

 برای آشنایی با این ویژگی، لازم است در رابطه با اصطلاح RAII آشنا شوید، برای این منظور مقالهٔ زیر را برای مطالعه پیشنهاد می‌کنم.

 

 

صفت‌های استاندارد جدید مانند، [[fallthrough]]، [[maybe_unused]] و [[nodiscard]] استاندارد ۱۷

این بحث به خودی خود بسیار جذاب است، بنابراین برای آن یک مقالهٔ ویژه در نظر گرفته‌ام که در ادامه می‌توانید به آن مراجعه کنید.

 

ویژگی فضاهای نام تو در تو (Nested namespace) استاندارد ۱۷

فضاهای نام یکی از کاربردی‌ترین ویژگی‌های سی++ از زمان استاندارد ۱۱ به بعد می‌باشد که نحوهٔ تعریف آن به صورت زیر است:

namespace Base {
  namespace Person {
    class PersonInfo {
    public:
      std::string name = {"Kambiz"};
    };
  }
}

در ادامهٔ استاندارد ۱۷ بهبود آن به شیوهٔ تو در تو صورت گرفته است و می‌تواند به صورت زیر تعریف شود:

namespace Base::Person {
    class PersonInfo {
    public:
      std::string name = {"Kambiz"};
    };
}

در نهایت دسترسی به فضای نام و اعضای آن به همان شیوهٔ ساده ممکن است:

Base::Person::PersonInfo pInfo;
  std::cout << pInfo.name << std::endl;

 

یک کاراکتر u8 لفظی استاندارد ۱۷

این ویژگی برای ترجمهٔ صحیح کاراکتر‌ها به اسکی (ASCII) در پلتفرم‌های مختلف استفاده می‌شود.

auto c = {u8'C'};

و یا به صورت یک رشتهٔ کامل:

auto str = u8"سلام";
  std::cout << str << "/n";

 

امکان استفاده از auto در template  استاندارد ۱۷

این ویژگی امکان این را می‌دهد تا نوع پارامتر‌ها را در الگو‌ها تعریف کنیم، در استاندارد ۱۴ این ویژگی به صورت زیر ممکن است:

template<typename Type, Type x> constexpr auto value = x;
int main()
{   
   auto x = value<int,3>;
   return 0;
}

و اینک به لطف استاندارد ۱۷ استفاده از کلمهٔ کلیدی auto نیز فراهم شده است که به طور زیر تعریف می‌شود:

template<auto x> constexpr auto value = x;
 
int main()
{   
   auto x = value<3>;
 
   return 0;
}

نوع متغیر x توسط کامپایلر استنباط می‌شود، البته باید در نظر داشت این ویژگی در استفاده از variadic templates هم کاربرد دارد. به مثال زیر توجه کنید:

template<auto ... values> struct A {};
 
int main()
{   
   auto k = A<1, 2, 'c'>();
   return 0;
}

الفاظ رشته‌ای (لیترال) با ممیز شناور‌ (Floating point) در مبنای هگزادسیمال استاندارد ۱۷

در استاندارد ۱۷ ممیز شناور در مبنای هگزادسیمال اضافه شده است. اگر یک حرف شناور لفظی، آغازش با دنبالهٔ کاراکتر‌های 0x یا 0X باشد، آن در مبنای هگزا دسیمال شناور محسوب می‌شود. در غیر این صورت در مبنای شناور دسیمال (مبنای ۱۰) تعریف می‌شود.

0x | 0X hex-digit-sequence exponent suffix
double d = 0x1.2p3; // hex fraction 1.2 (decimal 1.125) scaled by 2^3, that is 9.0

به مثال زیر توجه کنید:

#include <iostream>
int main()
{
  std::cout << 58.         << '\n'
            << 4e2         << '\n'
            << 123.456e-67 << '\n'
            << .1E4f       << '\n'
            << 0x10.1p0    << '\n';
}

نتیجهٔ تحت این ویژگی به این صورت است:

58
400
1.23456e-65
1000
16.0625

 

  • پسندیدن 1

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

جزئیات، به‌روز رسانی‌ها و ویژگی‌های C++20

معرفی و نمونه کد‌های کلاس std::span

کلاس std::span یک کلاس در C++20 است که برای نشان دادن (نمایش ظاهری) یک محدوده دنباله‌ای از اشیاء پیوسته بکار می‌رود. الگوی کلاس span یک شیء را توصیف می‌کند که می‌تواند به یک دنباله متوالی از اشیاء با اولین عنصر دنباله در موقعیت صفر ارجاع دهد. یک span می‌تواند دارای دامنه‌ی استاتیک باشد، در این صورت تعداد عناصر در دنباله در زمان کامپایل مشخص است و در نوع خودشان رمزگذاری شده‌اند و یا دامنه‌ی داینامیک دارد. اگر یک span دارای دامنه‌ٔ داینامیک باشد، به طور معمول، پیاده‌سازی آن شامل دو عضو است: یک اشاره‌گر به T و یک اندازه است. یک span با دامنه‌ٔ استاتیک ممکن است فقط یک عضو داشته باشد: یک اشاره‌گر به T.

template<
    class T,
    std::size_t Extent = std::dynamic_extent
> class span;

برای استفاده از کلاس std::span، باید ابتدا کتابخانه <span> را به کدتان اضافه کنید. سپس برای ایجاد یک شیء از این کلاس، می‌توانید از یک اشاره‌گر به شروع دنباله و طول آن استفاده کنید. برای مثال: 

#include <span>
#include <iostream>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    std::span<int> mySpan(arr, 5);
    
    for (int i : mySpan) {
        std::cout << i << " ";
    }
    
    return 0;
}

در این مثال، یک آرایه از نوع int با ۵ عضو تعریف شده و سپس یک شیء از کلاس std::span با استفاده از این آرایه و طول آن ایجاد می‌شود. سپس با استفاده از حلقه for، اعضای دنباله در خروجی چاپ می‌شوند.

استفاده از std::span می‌تواند در کدهایی که بر روی داده‌های چند بعدی یا برای داده‌هایی که آن‌ها نمی‌توانند با طول ثابت در داخل یک آرایه شبیه‌سازی شوند، مفید باشد. همچنین، با استفاده از std::span می‌توان با مراجعه به همه اعضای یک آرایه به صورت پویا از زمان اجرا، از یک پیاده‌سازی معمولی با تراکم حافظه کمتر استفاده کرد. همچنین استفاده از std::span برای پشتیبانی از روش‌های پیشرفته‌تر و بازبینی کدها مفید است.

اینجا یک نمونه از استفاده از std::span در یک کد C++20 آورده شده است:

#include <iostream>
#include <span>

int main() {
    int arr[] = {1, 2, 3, 4, 5};

    std::span<int, 5> s(arr); // s refers to the whole array

    for (auto& elem : s) { // range-based for loop
        std::cout << elem << ' ';
    }
    std::cout << '\n';
    
    std::span<int, 3> s2(arr + 1, 3); // s2 refers to {2, 3, 4}

    for (auto& elem : s2) {
        std::cout << elem << ' ';
    }
    std::cout << '\n';
}

در این کد، یک آرایه از 5 عدد تعریف شده است. سپس با استفاده از std::span، دو نمونه برای این آرایه تعریف شده است. پس از آن ، با استفاده از حلقه for ، مقادیر در هر دو نمونه std::span به ترتیب چاپ شده و تفاوت بین آن‌ها نیز نشان داده شده است.

برخی از مزایای این کلاس به صورت زیر است:

  • کد مطمئن‌تر: به دلیل استفاده از نمای مناسبی از ارث‌بری، این کلاس امکان بازنویسی کد و تجدید نظر در طراحی را فراهم می‌کند.
  • کاربردهای متعدد: توانایی نشان دادن داده‌های پیوسته با هر نوع، دنباله‌های داخلی و خارجی، بردارها، ماتریس‌ها و موارد دیگر، std::span را به یک وسیله کارآمد در برنامه‌نویسی ترکیب‌شدها و هم‌زمان‌سازی داده‌ها تبدیل کرده است.
  • عملکرد بهتر: به دلیل این که std::span یک کلاس ساده به همراه تعریف مجددی از iterator (https://en.cppreference.com/w/cpp/iterator) هاست، عملیاتی مانند خواندن، نوشتن و مرتب سازی داده‌ها، بسیار سریعتر از زیربرنامه‌های برنامه سازی بهینه شده است.
  • پشتیبانی از تشخیص خطا: با استفاده از std::span، می‌توان یک شیء معتبری ایجاد کرد که در آن تغییرات اندیس باید در محدوده معتبر واقع شود که باعث بهبود تشخیص خطا در کد می‌شود.

اینجا یک نمونه کد ورودی با std::span برای محاسبه میانگین اعداد یک محدوده از داده هاست که توضیحات کد نیز در کد ذکر شده است:

#include <iostream>
#include <span>
#include <algorithm>

double average(std::span<int> ns)
{
    if (ns.empty())
        throw std::invalid_argument("empty span");
    if (ns.size() > static_cast<size_t>(std::numeric_limits<int>::max()))
        throw std::invalid_argument("span size exceeds int max");
    if (std::any_of(ns.begin(), ns.end(), [](const int& n) { return n < 0; }))
        throw std::invalid_argument("span contains negative values");
    return static_cast<double>(std::accumulate(ns.begin(), ns.end(), 0)) / ns.size();
}

int main()
{
    int arr[] = { 1, 2, 3, 4, 5 };
    std::span<int> span_arr(arr, 5);
    try {
        std::cout << average(span_arr) << '\n';
    } catch(const std::exception& ex) {
        std::cerr << "Error: " << ex.what() << '\n';
    }
    return 0;
}

 

در کد زیر، یک std::span از یک آرایه از اعداد پشت سر هم ایجاد شده است و سپس به عنوان ورودی به تابع calculate_mean() منتقل شده است. تابع calculate_mean() به صورت یک حلقه که به ازای عنصری که به عنوان ورودی دریافت می کند، محدوده داده ها را پیمایش می کند و میانگین اعداد را محاسبه می کند.  با استفاده این تابع و تعریف یک آرایه از اعداد، برنامه قادر است میانگین اعداد را محاسبه کند.

#include <iostream>
#include <span>

double calculate_mean(std::span<double> nums)
{
    double sum = 0.0;
    for (auto num : nums) {
        sum += num;
    }
    return sum / static_cast<double>(nums.size());
}

int main()
{
    double nums[] = {2.0, 3.0, 5.0, 7.0, 11.0, 13.0};
    std::span<double> nums_span(nums, std::size(nums));
    double mean = calculate_mean(nums_span);
    std::cout << "mean = " << mean << std::endl;

    return 0;
}

کاربرد std::span در ورودی توابع

یکی از استفاده های مهم std::span ، به عنوان ورودی تابع است. با استفاده از std::span به عنوان ورودی، می توان به سادگی یک محدوده از داده ها را به یک تابع انتقال داد و از انتقال داده های اضافی و همچنین رعایت روشن بودن کد استفاده کرد. 

با استفاده از std::span به عنوان ورودی تابع، عملیات از هر نوع می تواند مستقل از نوع داده های کانتینر باشد و به همین دلیل کد تمیز تر و بیشتر چند منظوره خواهد بود.

#include <iostream>
#include <span>

double calculateAverage(std::span<double> nums) {
    double sum = 0;
    for (auto num : nums) {
        sum += num;
    }
    return (nums.size() > 0) ? sum / nums.size() : 0;
}

int main() {
    double data[] = {2.5, 3.8, 4.2, 1.7, 6.5};
    double average = calculateAverage(data);

    std::cout << "Average: " << average << std::endl;

    return 0;
}

در این کد، تابع calculateAverage یک std::span از نوع double به عنوان ورودی دریافت می کند و با استفاده از آن، میانگین عناصر را محاسبه می کند. سپس در تابع main یک آرایه از اعداد اولیه تعریف شده است که به عنوان ورودی به تابع calculateAverage ارسال می شود و سپس میانگین محاسبه شده چاپ می شود.

استفاده از std::span به خصوص زمانی مناسب است که به دنبال ارسال یک محدوده از داده ها به تابع هستیم، بدون آنکه نیاز به کپی کردن داده ها باشد. در این حالت، استفاده از std::span به جای استفاده از نشانگر به عنوان ورودی تابع، توصیه می شود. با استفاده از std::span، می توان محدوده ای از داده ها را مستقیماً به تابع انتقال داد و از کپی نشانگر آندونه و داده های مربوط به آن جلوگیری کرد و در عین حال، کد را شفاف تر و آسان تر قابل فهم نیز می کند.

 

کاربرد std::span در کلاس‌ها

استفاده از std::span در کلاس ها، می تواند در طراحی کلاس هایی که بر روی داده هایی فیکس‌شده کار می کنند، مفید باشد. این کار به تشخیص و جلوگیری از خطرات مربوط به ارجاع به اشاره یا نشانگر اشاره که به محدوده ای خارج از داده های کلاس مستقر شده اند، کمک می کند. 

#include <span>

class DataProcessor {
private:
  std::span<const int> data;
public:
  explicit DataProcessor(std::span<const int> d) : data(d) {}
  double calculateMean() const {
    double sum = 0.0;
    for (auto num : data) {
      sum += num;
    }
    return sum / static_cast<double>(data.size());
  }
};

همچنین، می‌توان با تعریف تابع‌هایی که با std::span کار می کنند، از صرفه جویی در حجم کدها خود لذت برد.

اینجا یک نمونه کد با استفاده از std::span در طراحی یک کلاس برای مدیریت یک آرایه با سایز ثابت است:

#include <array>
#include <span>

template <typename T, std::size_t N>
class FixedArray {
public:
    FixedArray(std::array<T, N>& arr) : data(arr), memory(data) { }

    std::span<T, N> memory;

private:
    std::array<T, N>& data;
};

در این کد، FixedArray یک کلاس است که یک آرایه با سایز ثابت را مدیریت می‌کند. با استفاده از std::span، ما می‌توانیم برای نگهداری داده‌ها از حافظه‌ای استفاده کنیم که قبل تر allocated شده است (در اینجا داده‌ها از آرایه data استخراج شده و به صورت پویایی در memory نگهداری می‌شوند). به این ترتیب، ما از خطرات ارجاع به اشاره به محدوده‌های خارج از داده ها به دلیل دستکاری در آرایه، محافظت می‌کنیم.

  • پسندیدن 1

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر
ارسال شده در (ویرایش شده)

جزئیات، به‌روز رسانی‌ها و ویژگی‌های C++23

همانطور که می دانیم، مدیریت خطا در سی‌پلاس‌پلاس به وسیلهٔ بیانیه‌های try، catch و throw انجام می‌شود. این ویژگی به برنامه‌نویس این امکان را می‌دهد که خطاها را شناسایی کرده و به دسته‌بندی کرده و سپس به شکل مناسبی برخورد کند.

همچنین کلاس‌هایی مانند std::exception یک کلاس پایه در سی‌پلاس‌پلاس است که برای نمایش استثناء‌ها (خطاها) در هنگام اجرای برنامه استفاده می‌شود. این کلاس یک رابط عمومی به نام what دارد که متنی که توضیح خطا را حاوی می‌شود، به عنوان یک رشته C-style (const char*) باز می‌گرداند.

 

مدیریت خطای جدید std::expected معرفی شده در استاندارد ۲۳

در استاندارد جدید ۲۳ گزینهٔ std::expected معرفی شده‌است که اجازه می‌دهد خطاها را بهتر مدیریت کنیم.

  • این نوع داده به شما این امکان را می‌دهد که یک عدد بازگشتی معمولی (نتیجه موفقیت‌آمیز) یا یک کد خطا (نتیجه ناموفق) را با هم در یک متغیر ذخیره کنید.
  • برای برنامه نویسانی که از این نوع داده استفاده می‌کنند، کد برنامه خواناتر و قابل‌فهم‌تر است.
  • استفاده از std::expected معمولاً در جاهایی مناسب است که خطاها قابل پیش‌بینی و مدیریت شوند.

در زیر یک نمونه کد در قالب مثال بر پایهٔ سی‌پلاس‌پلاس جدید آورده شده است:

import <print>;
import <expected>;

enum class ErrorType { InvalidName, NotFound, OtherError };

auto getName(std::string name) -> std::expected<std::string, ErrorType>
{
    if (name != "Kambiz") {
        return std::unexpected(ErrorType::InvalidName);
    }
    return name;
}

auto main() -> int {

    auto result = getName("Compez");

    if (result.has_value()) {
        std::println("Result: {}", result.value());
    } else {
        ErrorType error = result.error();
        switch (error) {
        case ErrorType::InvalidName:
            std::println("Error: Invalid Name!");
            break;
        case ErrorType::NotFound:
            std::println("Error: Not Found!");
            break;
        case ErrorType::OtherError:
            std::println("Error: Other Error!");
            break;
        }
    }

    return 0;
}

در اینجا، یک تابع به نام getName تعریف شده است که یک نام به عنوان ورودی دریافت می‌کند و یک std::expected را باز می‌گرداند. اگر نام "Kambiz" نباشد، یک std::unexpected با ErrorType::InvalidName ایجاد می‌شود و اگر نام معتبر باشد، خود نام به عنوان مقدار بازگشتی استفاده می‌شود.

سپس در تابع main، ما از تابع getName برای دریافت نتیجه استفاده می‌کنیم. اگر نتیجه دارای مقدار باشد (با فراخوانیhas_value())، آن مقدار با استفاده از value() چاپ می‌شود. اگر نتیجه دارای خطا باشد، ما با استفاده از error() نوع خطا را دریافت کرده و با استفاده از یک switch به تصمیمات مرتبط با نوع خطا می‌رسیم و پیام مناسب چاپ می‌شود. توجه داشته باشید که در دسترسی بهerror()، ممکن است بعضی از پیاده‌سازی‌های expected به جای error() از value() برای دسترسی به خطا استفاده کنند.

به نظر می‌رسد این ویژگی می‌تواند به صورت چشم‌گیری روش مدیریت خطاها را بهبود سازد.


ماژول‌ها و وارد کردن کتابخانه‌های استاندارد به پروژه به صورت ساده و بهینه توسطimport std; و import std.compat; در استاندارد ۲۳

قبلاً من توی پروژهٔ سل و حتی قالب PT یه بخشی برای بهبود و بهینه‌سازی فایل‌های کتابخانهٔ استاندارد (هدر فایل‌ها) به عنوان pch گذاشته بودم. این کار باعث می‌شد که پروژه در سرتاسرش هر جا اس کتابخانهٔ STL استفاده می‌شد رو نیازی به وارد کردن فایل‌ها نباشه. این کار موجب بهینگی کامپایل می‌شه. حالا توی استاندارد ۲۳ چیزی مشابه این موضوع رو به صورت استاندارد شده تعبیه کردن که از شلوغی و اضافات لازم به شدت جلو گیری می‌کنه و سرعت کامپایل هم افزایش پیدا می‌کنه. ⚡

بهتر بخوام توضیح بدم دیگه نیازی نیست کدی مثل زیر داشته باشید:

#include <algorithm>
#include <array>
#include <print>

auto main() -> int
{
    std::array<int, 10> s {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
    std::sort(s.begin(), s.end());
    for(auto el : s)
    {
        std::println("Sorted Index: {}", el);
    }
}

کافیه به شیوهٔ زیر بنویسید:

import std;

auto main() -> int
{
    std::array<int, 10> s {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
    std::sort(s.begin(), s.end());
    for(auto el : s)
    {
        std::println("Sorted Index: {}", el);
    }
}

در واقع استفاده از ;import std تمامی کتابخانه‌های استاندارد رو وارد می‌کنه و استفاده از ;import std.compat مثل همون هست اما با تفاوت این ‌که کتابخانه‌های عمومی C رو هم وارد خواهد کرد. فکرشو بکن ده‌ها و صد‌ها کتابخانه STL رو وارد فایل‌ها می‌کنی! اما الآن کافیه همین یه خط رو بنویسی 🙂 دنیای ماژول‌ها در سی‌پلاس‌پلاس جدید خیلی تمیزه!

ویرایش شده در توسط کامبیز اسدزاده
به‌روز رسانی استاندارد ۲۳.

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر
مهمان
این موضوع برای عدم ارسال قفل گردیده است.

  • کاربران آنلاین در این صفحه   0 کاربر

    هیچ کاربر عضوی،در حال مشاهده این صفحه نیست.

×
×
  • جدید...