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

کامبیز اسدزاده

بنیـــان گذار
  • تعداد ارسال ها

    505
  • تاریخ عضویت

  • روز های برد

    266

آخرین بار برد کامبیز اسدزاده در 21 دی

کامبیز اسدزاده یکی از رکورد داران بیشترین تعداد پسند مطالب است !

اعتبار در سایت

618 عالی

درباره کامبیز اسدزاده

اساتید
توسعه‌ دهنده بَک اِند
توسعه‌ دهنده فرانت اِند
توسعه دهنده فول اِستَک
منتور‌ها و مشاورین
  • تاریخ تولد 12 فروردین 1368

اطلاعات شبکه‌ای

موقعیت

  • شهر
    اورمیه

آخرین بازدید کنندگان نمایه

بلوک آخرین بازدید کننده ها غیر فعال شده است و به دیگر کاربران نشان داده نمیشود.

  1. کامبیز اسدزاده

    همه چیز در مورد مجوز و شرایط استفاده از کتابخانهٔ Qt

    یکی از مهمترین و پر‌مخاطب‌ترین سوألاتی که در مورد فریم‌ورک کیوت پرسیده می‌شود، شرایط استفاده و مجوز‌های مربوط به آن است؛ از آنجایی که این کتابخانه تحت پشتیبانی یک شرکت تجاری است، برخی از شرایط و قوائدی وضع شده است که در استفاده از آن باید دقت لازم را داشت. در این مقاله من قصد دارم به توضیحات و شفاف‌سازی کامل در این خصوص بپردازم که امیدوارم از آن بهره‌مند شده و به اشتراک بگذارید. بررسی مجوز‌های جامع Qt ابزار Qt، یک چهارچوب قدرتمند برنامه‌نویسی چندسکویی است که انواع مختلفی از مجوزها را ارائه می‌دهد تا به نیازهای متنوع کاربران خود پاسخ دهد. با توجه به تاریخچهٔ غنی‌ای که به آغاز توسعهٔ آن باز می‌گردد، Qt به تدریج به یکی از اصلی‌ترین بازیگران در زمینه توسعه نرم‌افزار تبدیل شده است که در این مقاله به آن اشاره می‌کنیم. Qt تحت چندین گزینه مجوز مختلف قرار دارد که برای توسعه نرم‌افزارهای مختلف مناسب هستند که به صورت زیر تعریف شده‌اند. مجوز تجاری Qt فریم‌ورک کیوت، زیر مجوزهای تجاری مناسبی را برای توسعه نرم‌افزارهای تجاری فراهم کرده است که کاربران نمی‌خواهند کد منبع خود را با دیگران به اشتراک بگذارند یا نمی‌توانند با شرایط نسخه 3 مجوز GNU LGPL (GNU Lesser General Public License) سازگاری یابند. مجوز LGPL Qt این مجوز برای توسعه نرم‌افزارهای Qt مناسب است، تا زمانی که شما می‌توانید با شرایط نسخه 3 مجوز GNU LGPL (یا GNU GPL نسخه 3) سازگار باشید. مجوز بازار Qt (Qt Marketplace) اجزای Qt تحت توافق‌نامه مجوز بازار Qt مناسب برای توسعه نرم‌افزارهای Qt هستند، معمولاً با شرایط مجوز تجاری یا GNU LGPL (یا GNU GPL نسخه 3) برنامه‌ریزی می‌شوند. استفاده از کد، از طریق مجوزهای متن‌باز فریم‌ورک Qt شامل کدهای شخص ثالثی است که تحت مجوزهای خاص متن‌باز از نویسندگان اصلی مجوزدهی شده‌اند. برخی از سوأل و پرسش‌های جامعه و تیم کیوت در رابطه با مجوز‌ها و اهداف آن‌ها در توسعه چرا Qt همچنین زیر مجوز نرم‌افزار متن باز نیز منتشر می‌شود؟ ما به جنبش نرم‌افزار آزاد اعتقاد داریم که استفاده از نرم‌افزار با حقوق وظایف خاصی همراه است. استفاده از مجوزهای نرم‌افزار متن باز، به کاربران چهار درجه اصلی از آزادی را در استفاده از برنامه‌ها یا دستگاه‌های Qt می‌دهد: آزادی اجرای برنامه برای هر هدفی. آزادی مطالعه نحوه عمل برنامه و سازگارسازی آن با نیازهای خاص. آزادی توزیع نسخه‌های کپی شده تا بتوانید به همسایه خود کمک کنید. آزادی بهبود برنامه و انتشار بهبود‌های خود به عموم، تا کل جامعه بهره‌مند شود. این آزادی‌ها غیرقابل مذاکره و مطلق هستند، نمی‌توان آنها را به صورت انتخابی یا جزئی تجربه کرد، شما همچنین موظف به انتقال آنها به کاربران خود هستید. چرا شما توافقی با KDE در مورد مجوزهای خود دارید؟ KDE چیست و تاریخچهٔ Qt و KDE چگونه است؟ توافق بین Qt و KDE دربارهٔ مجوزها، ریشه در تاریخچهٔ مشترک این دو نهاد دارد. KDE (kde.org) مخفف محیط کاری دسکتاپ (Desktop Environment) است که یک جامعهٔ بین‌المللی نرم‌افزار آزاد است و در سال ۱۹۹۶ تأسیس شد. KDE به خاطر محیط کاری Plasma Desktop شناخته می‌شود که به عنوان محیط کاری پیش‌فرض در بسیاری از توزیع‌های لینوکس به کار می‌رود. نرم‌افزارهای KDE بر پایهٔ چارچوب Qt ساخته می‌شوند. در اوایل توسعهٔ Qt، این چارچوب از یک مدل مجوز دوگانه برخوردار بود و کد منبع آن تحت مجوزهای متن باز اختصاصی قابل دسترس بود. با درک اهمیت Qt برای پروژه‌های خود، KDE تلاش کرد تا توافقاتی برای اطمینان از دسترسی به Qt تحت مجوزهای مناسب متن باز، حتی اگر Trolltech (شرکت بنیان‌گذار Qt) به تصرف بشود یا ورشکست شود، به دست آورد. نتیجهٔ این تفاهم، بنیاد آزاد KDE Qt (KDE Free Qt Foundation) تأسیس شد و توافق‌نامه بنیاد آزاد KDE Qt ایجاد شد. بنیاد آزاد KDE Qt یک سازمان با هدف ایمن کردن دسترسی به چارچوب Qt برای توسعهٔ نرم‌افزارهای آزاد و به‌ویژه برای توسعهٔ نرم‌افزارهای KDE است. این بنیاد در ابتدا توسط Trolltech و سازمان غیرانتفاعی حقوقی KDE (KDE e.V.) در سال ۱۹۹۸ تأسیس شد و یک توافق‌نامهٔ مجوز دارد که تأمین می‌کند که Qt برای پلتفرم‌های اصلی دسکتاپ و موبایل تحت مجوزهای LGPLv3 و GPLv3 در دسترس است. این توافق‌نامه در طی سال‌ها چندین بار به‌روزرسانی شده است، عمدتاً به دلیل انجام معاملات مرتبط با Qt یا به‌روزرسانی مجوزها و پلتفرم‌ها. عدم رعایت محدودیت‌های مجوزهای LGPL/GPL چه تبعاتی دارد؟ اگر نرم‌افزاری که از این کتابخانه‌های مجوز متن‌باز استفاده می‌کند، به طور کامل الزامات مجوز را رعایت نکند، شما حق استفادهٔ مجوز و حقوق توزیع مرتبط با آن را از دست خواهید داد. همچنین لازم به ذکر است که در بیشتر کشورها، نقض حقوق نسخهٔ پدیدآورندگان یک نقض تشریعی است، نه نقض قرارداد، و بنابراین تدابیر تشریعی مرتبط با این موضوع اعمال می‌شود. برای کسب اطلاعات بیشتر در مورد GPL، می‌توانید به صفحه FAQ GPL از لینک آن مراجعه کنید. آیا می‌توانم از نسخهٔ متن باز جوامع برای توسعه محصول تجاری خود استفاده کنم؟ این بستگی به نحوهٔ ارائه و ارائهٔ محصول شما دارد. نسخهٔ متن باز Qt اصلی به طور عمده تحت مجوز LGPL نسخه 3 و GPLv2/v3 منتشر می‌شود. شما باید الزامات مجوزهای این گونه را که در زمان استفاده از Qt در محصول خود باید رعایت کنید. تفاوت بین LGPLv2 و LGPLv3 چیست؟ LGPLv3 نسخه فعلی مجوز GNU Lesser General Public License است. LGPLv2.1 یک نسخه قدیمی‌تر است و برای پروژه‌های جدید توصیه نمی‌شود. هر دو مجوز همان هدف را دارند، یعنی حفاظت از آزادی کاربران برای استفاده و اصلاح نرم‌افزار تحت مجوز LGPL. LGPLv3 این هدف را به وضوح بیان می‌کند. شما باید چیز‌هایی را برای کاربر نهایی فراهم کنید تا نسخه اصلاح شدهٔ کتابخانه تحت مجوز LGPLv3 را نصب کرده و نرم‌افزار خود را با استفاده از آن کتابخانه اصلاح شده اجرا کند. در عمل، این به عنوان مثال به موارد زیر اشاره دارد: Tivoization – به وضوح اجازه ندهید دستگاه‌های بسته سازی‌شده ایجاد شود که کاربر نهایی حقوق مجوز LGPL برای کتابخانه‌های متن باز Qt را ندارد. DRM و رمزگذاری سخت‌افزاری – نمی‌توان از این تعهدات برای دور زدن این تعهدات استفاده کرد. انتقام از پتنت نرم‌افزار – جایی که تمام کاربران نرم‌افزار مجوزها را دارند، که این باعث بی‌معنی شدن انتقام از پتنت نرم‌افزارهایی که ممکن است در نرم‌افزار منتشر شده، می‌شود. وظایف من چیستند هنگام استفاده از Qt تحت مجوز LGPL؟ در ابتدا، باید توجه داشته باشید که تمامی ماژول‌های متن باز Qt تحت مجوز LGPLv3 در دسترس نیستند. برخی از ماژول‌ها برای استفاده در نرم‌افزارهای متن باز تحت GPLv3 قرار دارند و برخی از اجزاء توسعه‌یافته توسط شخص ثالث مانند موتور وب Chromium تحت مجوز LGPLv2.1 در دسترس قرار گرفته‌اند. زمانی که از ماژول‌ها و کتابخانه‌های Qt تحت مجوز LGPLv3 استفاده می‌کنید، برخی از وظایفی که باید رعایت کنید به شرح زیر است: هنگام استفاده از نرم‌افزار متن باز، باید از مجوز هر نمونه، قطعه کد منبع، ماژول و کتابخانه‌ای که در پروژه خود استفاده می‌کنید، آگاه باشید و مجوزهای مرتبط را ردیابی کنید. باید کد منبع کامل کتابخانه‌های Qt که استفاده کرده‌اید را به همراه تمام اصلاحات اعمال شده یا اعمال شده، به کاربران یا مشتریان خود ارائه دهید. به عنوان یک گزینه دیگر، می‌توانید پیشنهاد نامه‌ای با دستورالعمل‌هایی در مورد چگونگی دریافت کد منبع ارائه دهید. لطفاً توجه داشته باشید که این باید تحت کنترل شما باشد، بنابراین ارائه یک لینک به کد منبع ارائه‌شده توسط پروژه Qt یا شرکت Qt کافی نیست. مجوز LGPL به شما این امکان را می‌دهد که کد منبع خود نرم‌افزار را به عنوان «کاری که از کتابخانه استفاده می‌کند» خصوصی نگه‌دارید. به طور معمول، در اینجا پیشنهاد می‌شود که از اتصال پویا استفاده کنید (برای کامپایل استاتیک این مورد مجاز نیست و نیاز به تهیهٔ مجوز دارد). کاربر نهایی باید قادر باشد نرم‌افزار شما را با یک نسخه مختلف یا اصلاح‌شده از کتابخانه Qt مجدداً لینک کند. با LGPLv3، به وضوح ذکر شده است که کاربر باید قادر باشد باینری مجدداً لینک‌شده را بر روی دستگاه هدف خود اجرا کند. این وظیفه به شما محول است که کاربر را با همه ابزارهای لازم برای فعال کردن این فرآیند تجهیز کنید. برای دستگاه‌های جاسازی‌شده، این شامل فراهم‌کردن تمام ابزارهایی است که برای کامپایل کتابخانه استفاده‌شده به کاربران مورد نیاز است. برای اجزاء مجوزده LGPLv3، شما موظف به ارائه دستورالعمل‌های کامل در مورد نصب کتابخانه اصلاح‌شده بر روی دستگاه هدف هستید (این با LGPLv2.1 به طور واضح بیان نشده است، اگرچه اجرای برنامه در برابر نسخهٔ اصلاح شدهٔ کتابخانه با هدف اعلام شده در مجوز است). کاربری که از یک برنامه یا دستگاه که از نرم‌افزار متن باز تحت مجوز LGPL استفاده می‌کند، باید از حقوق خود مطلع شود، با ارائه یک نسخه از مجوز LGPL به کاربر نهایی و نمایش اعلان مشهور در مورد استفاده‌ شما از نرم‌افزار متن باز باید اعلام شود. این آزادی‌ها به هیچ وجه توسط شرایط دیگر مجوز گزینشی نمی‌توانند محدود شوند؛ اگر یک برنامه به کلی از تمام وظایفی که در بالا ذکر شده است پیروی نکند، اجازه توزیع آن به هیچ وجه داده نمی‌شود. همچنین باید اطمینان حاصل کنید که از هیچ ماژولی که تحت مجوز GPL استفاده نمی‌کنید. آیا نیاز است که از مجوز LGPL هنگام استفاده از نسخهٔ تجاری Qt نگران باشم؟ به طور معمول، خیر. هنگام استفاده از نسخهٔ تجاری مجوزگذاری شده Qt، ما تقریباً تمامی بخش‌ها را تحت شرایط یک مجوز تجاری ارائه می‌دهیم. هرچند، چندین ماژول در Qt از کد منبع پروژه‌های متن باز شخص ثالث مانند Qt WebEngine استفاده می‌کنند که از پروژه Chromium با مجوز LGPLv2.1 استفاده می‌کند. بنابراین، هنگام استفاده از این ماژول‌ها، شما باید از تعهدات مجوز مرتبط رعایت کنید، در مورد Chromium این موضوع به مجوز LGPLv2.1 اشاره دارد. تمامی ماژول‌ها و وابستگی‌های شخص ثالثی که توسط ماژول‌های مختلف Qt استفاده می‌شوند، در مستندات Qt برای هر نسخه از Qt مستند شده‌اند. به عنوان یک کاربر مجوز تجاری، در عمل، تنها نیاز دارید که به تعهدات مجوز LGPLv2.1 اهمیت بدهید، و تنها اگر از Qt WebEngine استفاده کنید. چه کاری باید انجام دهم؟ مطمئن نیستم که مطابق مجوزهای متن باز هستم؟ از مجوزهای متن باز گیج شده‌ام، چه باید انجام دهم؟ همیشه خوشحال هستیم که با شما درباره وضعیتتان صحبت کنیم، اما ما در جایی نیستیم که مشاوره حقوقی ارائه دهیم. همیشه توصیه می‌شود با یک وکیل که با مجوزهای متن باز آشنا است، تماس بگیرید تا یک بررسی کامل از پروژه شما صورت گیرد و تصمیم گیری شود که آیا شما می‌توانید تمامی تعهدات مجوزهای متن باز مربوطه (مانند LGPLv/GPLv) را انجام دهید یا خیر. مجوز تجاری Qt چگونه کار می کند؟ آیا همه توسعه دهندگان من باید مجوز معتبر Qt داشته باشند؟ در رابطه با مجوز‌های تجاری، هر کاربر Qt باید مجوز تجاری Qt مختص خود را داشته باشد. طراحان رابط کاربری، هنرمندان فنی، توسعه‌دهندگان نرم‌افزار یا مهندسان اتوماسیون تست ممکن است انواع مختلفی از مجوزهای Qt داشته باشند، اما هر فرد باید یک مجوز اشتراک معتبر داشته باشد. آیا می‌توانم کد نوشته‌شده با Qt متن باز را با Qt تجاری مجوزگذاری شده ترکیب کنم؟ خیر. اگر می‌خواهید از Qt متن باز به یک مجوز تجاری مهاجرت کنید، لطفاً با فروشگاه Qt تماس بگیرید. برای این سوال، موارد بیشتری نیز در لینک FAQ مجوزگذاری تجاری Qt وجود دارد. آیا امکان توزیع برنامه‌های توسعه یافته با نسخهٔ متن باز Qt از طریق فروشگاه‌های عمومی وجود دارد؟ هر فروشگاه اپلیکیشن شرایط و مقررات منحصر به فردی دارد که ممکن است با توزیع برنامه‌ها تحت مجوزهای LGPL یا GPL سازگار یا سازگار نباشد. مجوز تجاری Qt با شرایط و مقررات تمامی فروشگاه‌های اپلیکیشن معتبر سازگار است و بنابراین معمولاً بهترین گزینه برای توزیع یک برنامه به صورت منبع بسته در فروشگاه‌های مختلف است. من شروع به توسعه یک محصول با استفاده از نسخهٔ متن باز Qt کرده‌ام، حالا می‌توانم یک نسخهٔ تجاری از Qt خریداری کرده و کدم را تحت آن مجوز قرار دهم؟ بله. پروژه‌های توزیع‌شده تحت نسخهٔ تجاری Qt نیز باید تحت نسخهٔ تجاری Qt توسعه یابند. اگر قبلاً توسعه را با نسخهٔ متن باز Qt شروع کرده‌اید، ما به همکاری برای یافتن یک راه‌حل برای انتقال پایه کد شما از حاکمیت متن باز به مجوز تجاری می‌پردازیم. اگر از ابتدا مطمئن نیستید که از کدام مجوز یا نسخه برای شروع توسعه استفاده کنید، توصیه می‌شود با The Qt Company تماس بگیرید تا بر اساس نیازهای توسعه‌ی خود شما راهنمایی شود. ممکن است در یک برنامه از کتابخانه‌های دارای مجوز LGPLv2.1 و LGPLv3 استفاده کرد؟ بله، امکان استفاده از هر دو نسخهٔ مجوز LGPLv2.1 و LGPLv3 در یک برنامه وجود دارد، به عنوان مثال با استفاده از آن‌ها به عنوان کتابخانه‌های جداگانه به عنوان shared libraries. انجام این کار نیاز به تغییر مجوز در هیچ یک از کتابخانه‌ها ندارد و در صورت نیاز، امکان انتخاب یک مجوز مولد برای برنامه وجود دارد. ماتریس سازگاری GNU نشان می‌دهد که من نمی‌توانم LGPLv2 و LGPLv3 را ترکیب کنم؟ اگر کد LGPLv2.1 و کد LGPLv3 در کتابخانه‌های جداگانه به عنوان shared libraries قرار داده شوند، می‌توانند در یک برنامه استفاده شوند، و شما می‌توانید برنامه خود را با یک مجوز مالکیتی / LGPLv2.1 / LGPLv3 به دلخواه خود مجوزگذاری کنید. در مورد نسخهٔ مجوز LGPL/GPL که شما استفاده می‌کنید، چه کسانی مهم هستند؟ شما، مشتریان شما و کاربران نهایی، مگر اینکه از Qt تحت یک مجوز تجاری استفاده کنید. مجوزهای copyleft مانند LGPL و GPL به این معناست که مجوز با محصول شما به مشتریان و کاربران یا راه‌حل شما همراه می‌شود. با توجه به تمامی توضیحات موجود، به طور خلاصه چه زمانی نیاز به تهیهٔ مجوز‌های کیوت داریم؟ تهیهٔ مجوز کتابخانه Qt بستگی به نوع کاربرد و نیازهای پروژه دارد. جوانب مختلفی که تعیین می‌کنند چه زمانی نیاز به مجوز Qt داریم و چه مواردی ممکن است بدون نیاز به مجوز باشند. استفادهٔ شخصی: نیاز به مجوز: اگر برنامه‌نویس قصد استفاده از Qt را برای توسعهٔ پروژهٔ شخصی و خصوصی دارد بدون انتشار کد منبع، نیاز به مجوز ندارد. در این حالت، می‌توان از Qt به صورت رایگان استفاده کرد. بدون نیاز به مجوز: استفاده از Qt برای پروژه‌های شخصی بدون هدف انتشار کد منبع با محدودیتی همراه نخواهد بود. توسعهٔ نرم‌افزار باز (Open Source): نیاز به مجوز: اگر قصد توسعهٔ یک نرم‌افزار منبع باز با Qt را دارید و می‌خواهید کد منبع خود را نیز تحت یک مجوز Open Source انتشار دهید، نیاز به مجوز GPL یا LGPL خواهید داشت. بدون نیاز به مجوز: اگر نیازی به انتشار کد منبع ندارید و از Qt برای پروژه منبع باز خود استفاده می‌کنید، می‌توانید از نسخهٔ Qt با مجوز LGPL بدون مشکل استفاده کنید. توسعهٔ نرم‌افزار تجاری (Commercial Software): نیاز به مجوز: اگر قصد توسعهٔ نرم‌افزار تجاری دارید و نمی‌خواهید کد منبع خود را انتشار دهید، نیاز به مجوز تجاری Qt دارید. بدون نیاز به مجوز: اگر از Qt برای توسعهٔ یک نرم‌افزار تجاری استفاده می‌کنید و توافق به اشتراک‌گذاری کد منبع ندارید، می‌توانید از نسخهٔ تجاری Qt بهره‌مند شوید. توسعهٔ نرم‌افزار تحت LGPL: نیاز به مجوز: اگر می‌خواهید نرم‌افزار تجاری توسعه دهید، اما نیاز به استفاده از کتابخانه Qt دارید و می‌خواهید تغییرات خود را در کتابخانه منتشر کنید، باید از مجوز LGPL استفاده کنید. بدون نیاز به مجوز: اگر قصد استفاده از Qt را در یک نرم‌افزار تجاری با حفظ محرمانگی کد دارید، می‌توانید از مجوز تجاری Qt بهره‌مند شوید. برخی از نکات را نیز باید در نظر بگیرید، مانند نوع کامپایل و نوع مجوز‌های قابل پذیرش در فروشگاه‌ها که عموماً همهٔ آن‌ها را توضیح دادیم به چه صورت هستند.
  2. کامبیز اسدزاده

    جزئیات، به‌روز رسانی‌ها و ویژگی‌های 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 رو وارد فایل‌ها می‌کنی! اما الآن کافیه همین یه خط رو بنویسی دنیای ماژول‌ها در سی‌پلاس‌پلاس جدید خیلی تمیزه!
  3. توضیحاتی که در این پست ارائه می‌کنم، به منظور این نیست که بگم چیزی بد هست یا چیزی خوب! یکی بهتر است و دیگری بدتر! اما دوست دارم بیشتر با جو تبلیغاتی غالب روی چیزی نظر ندیم و در برنامه‌نویسی هم شخصاً تمایل دارم به بالاترین سطح ممکن از آزادی عمل در یک ابزار برسم که همه چیز رو برای یک برنامه‌نویس فراهم می‌کنه. مثالی که قبلاً زده بودم همون بحث باغ‌وحش و حیاط وحش بهترین مثال ممکن هست که می‌تونستم بزنم ولی خب اهل تفکر باید باشی تا بفهمی چی گفتم. بذار یه چیز‌هایی در مورد Rust و C و ++C بهتون بگم تا دیگه نیازی برای ادامهٔ بحث‌های پیش پا افتاده نباشه (این بحث‌ها مسخرست و صرفاً وقت شما رو می‌گیره، اما آگاهی داشتن در موردش می‌تونه دیدگاه بهتری برای پیشروی بهتون بده) اما موضوعاتی که بهش اشاره می‌کنم رو اگه کمی عمیق‌تر بهش دقت کنی، خواهی دید که چرا چیزی مثل سی‌پلاس‌پلاس واقعاً بی‌رقیبه. قبل از هر چیز بهتره مروری از به وجود اومدن این زبان‌ها رو داشته باشیم: وقتی در دههٔ ۷۰ میلادی زبان C به وجود اومد، به عنوان یک ابزار به شدت قابل تحسین با ۱۰۰٪ آزادگی عمل معرفی شد، شما هر سیستم و هر ساختاری رو که می‌خواستی می‌تونستی باهاش بسازی! به هر حال کامپیوتر یک جهان جدیدی بود و هر چیزی در اون می‌تونست یک فرصت باشه؛ همین الآن بعد از گذشت ۵۲ سال خیلی‌ها فکر می‌کنن این زبان منسوخ شده! در حالی که طبق آخرین مستندات N3096 استاندارد C23 در ۲ آوریل ۲۰۲۳ به صورت پیش‌نمایش منتشر شده و هنوز هم در حال توسعه و پیشرفته! یادتونه گفتم هیچ ابزار و فناوری‌ای تا زمانی که در حال توسعه باشه، غلطه که بهش بگیم منسوخ شد! تقریباً ۳۹ سال پیش، وقتی سی‌پلاس‌پلاس به وجود اومد کاملاً ویژگی‌های C رو به ارث برد، در واقع هر چیزی که C داره، هم مشکلات و هم مزایا در ++C هم وجود داره اما خیلی فراتر از مباحثی که فکرش رو می‌کردند به یک باره توسعه‌پذیر شد. خیلی خب باید بپذیریم مشکلاتی که C داشته را هم در بعضی جاها ++C خواهد داشت، اما نه به صورت یک مانع! چون برای همشون راهکار وجود داره، هیچ چیز بی دلیل ساخته نمیشه، این رو مطمئن باش به‌روز رسانی‌ها بی دلیل نیستند. در مورد Rust، که ۸ سال پیش وقتی به وجود اومد که حتی به ۱۰ سال هم عمر و پختگیش نمیرسه صرفاً تمرکزش به ادامهٔ مسیر‌های مشابه زبان‌های مدیریت شده بود اما در حوزه‌ها و منظور‌های متنوع‌تر که این موضوع جذابش می‌کنه. راست یک زبان سیستمی هست اما با دارا بودن خاصیت Ownership که به همراه یک سری قوانین مثل Transfer Rules و Borrowing خیال شما رو از بحث ایمنی راحت می‌کنه. همین موضوع مسیر Rust رو با C و ++C جدا می‌کنه و قابل قیاس نیستند که در ادامه می‌گم چرا. موضوع مدیریت خودکار حافظه این بحث برتری حساب نمیشه چون توی سی++ مدرن ما راهکار‌های مشخصی برای مدیریت این مسائل داریم. خب یعنی چی یه ابزار داشته باشیم که بیاد امکان برنامه‌نویسی سیستمی رو بده اما مطمئن؟! قطعاً یه جای کار داره می‌لنگه! عین اینه که بگی من اینترنت دارم ولی فیلترینگ شدیدی روش هست، بله نمی‌ذاره من آزادانه و اونطور که می‌خوام پیش برم، هرجا ریسکی بود به عهدهٔ خودمه هرجا خیری بود باز به نفع خودمه. زور و فشار هیچ‌وقت موجب پیشرفت عمیق نمیشه حتی در فناوری! چون شما اختیار عمل ندارید و محبورید با محدودیت‌هایی که اعمال می‌شه پیش‌روی کنید. ساختار مهمی که راست داره بحث موضوع Ownership یا همون مالکیت هست، این یعنی چی؟ یعنی مالک خودش شیء‌ای هست که مسئولیت مدیریت حافظهٔ اختصاص داده شده به یک شیء رو به عهده می‌گیره. در کنار این موضوع قانون انتقال یا همون Transfer می‌گه که هر شیء‌ای فقط یک مالک داره و مالکیت اون‌ها تنها می‌تونه به یک شیء دیگر منتقل بشه! این یک قانون اصلی و مهم در راست هست که برای تضمین این موضوع قانون امانت یا همون Borrowing می‌گه که اگه می‌خوای از یک شیء به عنوان مالک نهایی استفاده کنی، می‌تونی مالکیت به شکل امانت رو به شی‌ء دیگری انتقال بدی که در حالت قرضی یا موقتی ممکن هست اما اجازه نداری هرطور که دلت خواست ازش استفاده کنی. خب این قانون محدودیت‌های شدیدی رو ایجاد می‌کنه، اما در عوض بله تضمین می‌کنه که مدیریت حافظه مطمئن هست. این باعث می‌شه خطاهای حافظه به خاطر وجود مالکیت اختصاصی، که در زمان کامپایل، کامپایلر تعیین می‌کنه که چه زمانی باید حافظه آزاد بشه رو جلوگیری می‌کنه. شما نمی‌تونید به صورت آزاد روی مدیریت حافظه حرفی برای گفتن داشته باشید چون شما آزادی عمل ندارید. در مقابل در سی‌پلاس‌پلاس بدون هیچ محدودیتی از این موضوع بهره می‌برید. دسترسی به لایه‌های سخت‌افزاری عمیق و پشتیبانی از abi‌های سیستم‌عامل‌ها به صورت کامل تحت راست ممکن نیست مگر اینکه به صورت اختصاصی نسبت به هر abi در اختیار شما خارج از استاندارد‌ها قرار بگیره، چیزی که در سی‌پلاس‌پلاس همه چیز به صورت استاندارد در اختیار توسعه‌دهنده قرار می‌گیره. کتابخانه‌های استاندارد Rust قابلیت کنترل مستقیم روی ترد (نخ)‌ها رو ارائه نمی‌کنه هرچند مدعی هستن که از روش‌های crate در کامپایلر راست در زمان اجرا با استفاده از thread_priority‌ها قابل پیاده‌سازی هست اما با این حال، هیچ‌وقت در سطح فوریتی به اندازهٔ API‌های استاندارد ++C قابل استفاده نیست، حتی C هم در این حد و اندازه امکان مدیریت سخت‌افزار رو برای شما نمیده. در صورتی که در Rust لایهٔ امنیتی رو فعال هست (چیزی که به صورت پیش‌فرض در راست فعال هست) دیگه امکان دسترسی به لایه‌های سخت‌افزاری رو از دست خواهید داد. در حالی که سی++ این امکان رو به صورت کاملاً آزاد در اختیار شما قرار میده و شما با پذیرش خطر اون اگر تسلط خوبی داشته باشید می‌تونید به بهترین شکل ممکن دسترسی نامحدود به این موضوع رو در اختیار بگیرید. شما در راست فقط حق انتخاب بر مبنای قوائد از پیش تعریف شده رو دارید، یا ایمن باش و محدود باش، یا ایمن نباش و باز هم محدود باش! این در سی++ برعکسه! شما یا باید کد ایمن بنویسی و در عین حال به بالاترین کارآیی دسترسی داشته باشی، یا باید به خاطر عدم داشتن تسلط بالا خطر‌هاش رو بپذیری که صد البته برای کاهش مسائل راهکار‌های استاندارد‌های جدید بهترین گزینست. تمام چیزی که راست ادعا کرده کلاً بر مبنای محدودیت‌های اعمال شده هست، برای مثال شما هیچ راه استاندارد و بومی شده‌ای برای دسترسی API‌های سیستمی به شیوهٔ مستقل از سکو رو ندارید مگر مواردی چون windows-rs و مشابهش که کاملاً خارج از بحث استاندارد و به نوع سوم در دسترس توسعه‌دهنده‌ها قرار می‌گیرند و مناسب چند-سکویی واقعی نیست. جامعهٔ پخته و اکو‌سیستم راست هیچ‌وقت به اندازهٔ زبان‌های C و ++C گسترده نیست و کتابخانه‌های استانداردِ بی‌شماری از این بابت در اختیار توسعه‌دهنده‌ها قرار نگرفته و این قابلیت مقایسه با عمق مستنداتی که طی چندین دهه برای زبان‌های دیگه موجود هست رو نداره. راست به معنای واقعی کلمه یک زبان ایمن هست اما با فعال بودن لایهٔ ایمنی، قدرتمند نیست و زیرساخت‌های سنگین که قدرت مانور کامل روی سخت‌افزار رو به شما بده. راست به هیچ عنوان بهینگی لازم رو به خاطر قوائد ایمنی در زمان اجرا (Run-Time) رو نداره در حالی که در ++C شما بهینگی به شدت بالایی رو برای زمان اجرا می‌تونید اعمال کنید. در راست که مدعیه یک زبان سطح‌پایین هست، ما مفهومی به عنوان Placement new نداریم، حتی معنا هم براش نداره چون دیگه محدودیت مالکیت (Onwership) با این موضوع هم خونی نداره و چنین ادعاهایی رو راحت رد می‌کنه. در سطوح پیشرفته، توسعه‌دهنده در ++C با استفاده از Placement new، می‌تونه یک شیء رو در یک مکان خاص از حافظه ایجاد کنه، بدون اینکه حافظه جدیدی بهش اختصاص بده! این امکان به شما اجازه میده که به طور دقیق مشخص کنید کجا باید یک شیء ایجاد بشه! چیزی که حتی در C هم به اندازهٔ ++C در مورد کنترل، سازگاری و انعطاف‌پذیری در مدیریت حافظه رو به ارائه نمی‌کنه. و اما در مورد بحث مسائل زمان اجرا و کامپایل، بله راست به دلیل ویژگی‌هایی که داره در زمان کامپایل مشکلات قابل بروز در زمان اجرا رو کنترل می‌کنه، در مقابل استاندارد‌های جدید از سی‌پلاس‌پلاس نیز ویژگی‌هایی مثل Contracts‌ها و Concepts‌ها رو برای این منظور در نظر گرفته که اگه با استاندارد جدید آشنا نباشید طبیعتاً کد‌های شما در زمان اجرا ممکنه ایمن نباشه. خلاصهٔ کلام اینه که هر زبانی در جای خودش مزایا و معایب خودش رو داره که معمولاً برای تبلیغات و حمایت شدن توسط جامعه، طبیعیه که باید بعضی از مسائل رو نادیده بگیره و بعضی از مزایا رو بیشتر مطرح کنه. در مورد راست هم همینطور، در مورد سی‌پلاس‌پلاس هم همینطور! نا نمی‌تونیم بگیم همه چیز بده یا همه چیز خوبه! قطعاً در مقابل امنیت شک نکنید باید یک سری چیز‌ها رو در نظر بگیرید و در مورد آزادی توسعه توسط یک زبان هم همچنین. به‌روز رسانی‌های اخیر سی‌پلاس‌پلاس طوری پیش رفته که وقتی بخوای به عنوان یک زبان مدرن ازش استفاده کنی، اصولاً دیگه جای بحثی از نظر ترس و وحشت یا مشکلات حافظه یا چنین مسائلی باقی نمی‌مونه. این بر می‌گرده به توسعه‌دهنده که واقعاً از چه نسل و استانداردی تبعیت می‌کنه.
  4. بیت‌کوین در سال ۲۰۰۹ به عنوان یک ارز دیجیتال و یک پلتفرم غیرمتمرکز همتا به همتا راه انداخته شد که کنترل اموال را به همه افراد می‌دهد. ساتوشی ناکاموتو این پلتفرم را معرفی کرد و از آن زمان به کاربری گسترده رسیده و سرمایه‌گذاری با ارزش بازار بیش از ۳۵۳ میلیارد دلاری را به دست آورده است. به عنوان یک گزینه سرمایه‌گذاری، بیت‌کوین دارای ماهیت نوسانی است و برای افرادی که حاضر به پذیرش ریسک هستند، ثروت‌آفرین بوده است. حتی برخی از متخصصان مالی ادعا می‌کنند که قیمت یک بیت‌کوین ممکن است در چند سال آینده به بیش از ۴۰۰ هزار دلار برسد، این که این دارایی بهتر از طلا به عنوان یک ذخیره ارز باشد. فناوری مورد استفاده در بیت کوین نیز در نوع خود بی نظیر است. ناکاموتو استفاده از الگوریتم های ++C را برای طراحی این فناوری مالی انتخاب کرد، اما چرا؟ مدیریت حافظه مدیریت منابع یکی از حیاتی‌ترین مسائلی است که توسعه‌دهندگان در هنگام ایجاد نرم‌افزار در نظر می‌گیرند. برای اینکه یک نرم‌افزار بتواند کلیه ویژگی‌های خود را به دست آورده و همچنان در ارائه خدمات بسیار موثر باقی بماند، باید پروتکل‌های مناسب مدیریت منابع داشته باشد. در توسعه بلاکچین، وضعیت تا حد زیادی تفاوت ندارد. از آنجا که بلاکچین خدماتی را به میلیون‌ها نفر و نهاد ارائه می‌دهد، باید برای کارایی در ارائه خدمات بسیار مقیاس‌پذیر باشد. تحقیقات اخیر از Statista نشان می‌دهد که شبکه بیت‌کوین در سومین سه‌ماه سال ۲۰۲۰ بیش از ۳۵۰ هزار تراکنش روزانه داشت. بعضی از این تراکنش‌ها شامل مقادیر زیادی پول دیجیتال هستند و به عنوان نتیجه نیاز به محاسبات طولانی دارند. ایده اصلی ایجاد بلاکچین توسط ناکاموتو، ایجاد یک شبکه برای تسهیل تعاملات مالی و تسریع در فرآیندها بود. بهترین زبان برنامه‌نویسی برای یک سیستم با این ویژگی‌ها الگوریتم‌های سی‌پلاس‌پلاس است. الگوریتم‌های سی‌پلاس‌پلاس می‌توانند با استفاده بهینه از منابع و کنترل بر روی استفاده از CPU و حافظه، در سطح بهترین عمل کنند. این الگوریتم همچنین به بلاکچین اجازه می‌دهد تا بلوک‌ها را پذیرفته یا رد کند، بنابراین هر گونه تفکیک در بلاکچین را از بین می‌برد. استفاده از C++ بنابراین به پلتفرم کمک می‌کند تا با نرخ سریع با نقاط پایان مختلف تعامل کند. جداسازی کد توسعه نرم‌افزار، شامل بلاکچین، باید فضای کافی برای عملیات تعیین‌پذیر فراهم کند. در مورد بلاکچین، عملکردهای تعیین‌پذیر، هنگامی که به درستی اجرا می‌شوند، تضمین می‌کنند که تراکنش‌ها و فرآیندهای داخلی مانند قراردادهای هوشمند همواره به یک شیوه خدمت می‌کنند حتی زمانی که در دستگاه‌های مختلف قرار دارند. اما تنها راه توسعه‌دهندگان و متخصصان کد نحوه دستیابی کامل به عملیات تعیین‌پذیر را اعمال جداسازی کدها می‌دانند. چه چیزهایی باید توسعه‌دهندگان جدا کنند؟ از آنجا که عملکردهای اجرا شده تعیین‌پذیر هستند، توسعه‌دهندگان باید راهی برای جدا کردن عناصر غیرتعیین‌پذیر از کد قرار دهند. سی‌پلاس‌پلاس از قابلیت‌های فضای نام (namespace) بهره‌مند است که به برنامه‌های دیگر قابل انتقال هستند. این فضاهای نام به جلوگیری از تداخل در عملکرد کدها کمک می‌کنند. همچنین ویژگی کلاس وجود دارد که به جدا کردن و تعیین مرزها بین API کمک می‌کند. قابلیت اطمینان و رسالت ++C یکی از ویژگی‌های حیاتی دیگری که به انتخاب ساتوشی ناکاموتو از سی‌پلاس‌پلاس به عنوان زبان اصلی برنامه‌نویسی بیت‌کوین کمک کرد، ویرایش و به‌روز رسانی‌های اساسی سی‌پلاس‌پلاس است. ++C اغلب به‌روزرسانی می‌شود تا اطمینان حاصل شود که همواره باقی بماند و قابل اطمینان و به‌روز باشد. علاوه بر این، ++C دارای ابزارهای دیباگ و تجزیه و تحلیل مختلف است، تمامی این ابزارها به تقویت عملکرد آن کمک می‌کنند. این ابزارها همچنین امکان شناسایی هر مشکلی را در زمان برنامه‌نویسی فراهم می‌کنند. قابلیت اطمینان و ویرایش سی‌پلاس‌پلاس آن را به پایدارترین زبان برنامه‌نویسی برای توسعه بیت‌کوین تبدیل می‌کند که همچنین اطمینان می‌دهد که نرم‌افزار ساخته شده دارای امنیت بسیار بالاتری باشد. نخ‌ها (Threading) نخ‌ها یا ترد، در برنامه‌نویسی شامل یک مجموعه از دستورالعمل‌ها، فعالیت‌ها یا وظایفی هستند که می‌توانند به طور صاف یا هماهنگ با یکدیگر اجرا شوند. دو نوع عملکرد باید در هر نرم‌افزار یکپارچه باشند، یعنی وظایف موازی و غیرموازی. یک پروژه بلاکچین بیت‌کوین هرگز نمی‌توانست کار کند اگر وظایف موازی و غیرموازی هماهنگ عمل نمی‌کردند. اما یکی از پیچیده‌ترین چیزها در برنامه‌نویسی، ادغام این وظایف است و بیشتر زبان‌های برنامه‌نویسی در حال حاضر معمولاً تمرکز بر روی یکی از این دو وظیفه، یعنی موازی یا غیرموازی دارند. اما سی‌پلاس‌پلاس یکی از قابلیت‌های نخی قابل تحسین دارد که توسعه‌دهنده را قادر می‌سازد همزمان از هر دو وظیفه موازی و غیرموازی استفاده کند. سی‌پلاس‌پلاس می‌تواند به‌طور کارآمد نخ‌های چندگانه را اجرا کرده و امکان ارتباط همگانی و قابل اعتماد بین تمام نخ‌ها را فراهم کند. علاوه بر این، نخ‌های ایجاد شده توسط سی‌پلاس‌پلاس می‌توانند در نقطه بهینه‌ترین عمل کنند، بنابراین کل بلاکچین به طور بهینه عمل می‌کند. با توجه به عملکرد بهینه این زبان، می‌توان گفت یک دلیل دیگر که ساتوشی ناکاموتو از سی‌پلاس‌پلاس استفاده کرد، این است که این زبان امکان نخبندی آسان برای وظایف موازی و غیرموازی را فراهم می‌کند. قابلیت (Move Semantics) قابلیت (Move Semantics) یک عملکرد است که به توسعه‌دهندگان امکان می‌دهد محتوا را بین اشیاء جابجا کنند به جای اینکه فقط محتوا را کپی کنند. با استفاده از قابلیت جابه‌جایی اشیاء و ...، توسعه‌دهندگان و کاربران بر اساس نیاز دسترسی به کپی‌های مختلف اطلاعات دارند، که عملکرد را افزایش داده و تکرار را کاهش می‌دهد. تبعیت از استاندارد‌ها و رعایت قوائد انرژی سبز انرژی سبز یکی از چالش‌های اصلی در صنعت بلاکچین و تولید بیت‌کوین است. به دلیل محاسبات پیچیده و فرآیند استخراج معدنی که برای تولید بیت‌کوین انجام می‌شود، مصرف انرژی این فعالیت‌ها به سرعت افزایش می‌یابد. سی‌پلاس‌پلاس به عنوان زبان اصلی برنامه‌نویسی بیت‌کوین، به طور چشمگیری به بهینه‌سازی مصرف انرژی متمایل است. استانداردهای مصرف بهینه انرژی در طراحی و اجرای برنامه‌ها، این زبان را به یک انتخاب پایدار برای پروژه‌های مرتبط با بلاکچین و ارزهای دیجیتال می‌کند. این به معنای کاهش آثار منفی بر محیط زیست و همچنین صرفه‌جویی در هزینه‌های انرژی مرتبط با فرآیند تولید بیت‌کوین می‌باشد. همچنین، با توجه به گستردگی بیت‌کوین و تاثیر زیاد آن بر مصرف انرژی جهان، تلاش برای استفاده از زبان‌های برنامه‌نویسی با بهینه‌ترین مصرف انرژی، اهمیت فوق‌العاده‌ای پیدا کرده است. سی‌پلاس‌پلاس با امکانات بهینه‌سازی و مدیریت منابع به کاربران این امکان را می‌دهد که به نحوی کارایی انرژی را بهبود بخشند و در طولانی مدت، اثرات محیطی مرتبط با تولید بیت‌کوین را کاهش دهند. از این رو، اهمیت انتخاب این زبان برای توسعه بیت‌کوین نه تنها در جنبه‌های فنی بلکه در جنبه‌های محیطی نیز بیان می‌شود. بهتر است نظر سازندهٔ سی‌پلاس‌پلاس در مورد استفاده از این ابزار برای ارز دیجیتال را هم بدانیم در اشتراک بین خالق زبان برنامه‌نویسی سی‌پلاس‌پلاس، بیارنه استرواستروپ و ساتوشی ناکاموتو، اشاره به زبان برنامه‌نویسی ++C و موضوع ماینینگ بیت‌کوین با تأکید بر مصرف انرژی بالا و تأثیرات آن بر محیط زیست است. چندی پیش در یک پادکست هوش مصنوعی با مجری Lex Fridman، استرواستروپ در مورد نحوهٔ استفاده از سی‌پلاس‌پلاس و عدم کنترل بر نحوه استفاده از ابزارهای توسعه‌دهنده صحبت کرده و به‌ویژه به ماینینگ بیت‌کوین اشاره کرده است. او به عنوان خالق زبان سی‌پلاس‌پلاس ابراز خوشحالی از برخی از کاربردهای این زبان و ناراحتی از برخی دیگر اشاره کرده و به مصرف انرژی بالای ماینینگ بیت‌کوین اشاره کرده است. استرواستروپ از مصرف انرژی فعلی ماینینگ بیت‌کوین به خوشایندی خاصی احساس نمی‌کند و این موضوع را به دلیل انتخاب سی‌پلاس‌پلاس به عنوان زبان برنامه‌نویسی توسعه بیت‌کوین توسط ساتوشی ناکاموتو ذکر کرده است. از نظر استراس‌تروپ سی‌پلاس‌پلاس، یک زبان برنامه‌نویسی قدرتمند و گسترده است که در حوزه‌های مختلف برنامه‌نویسی مورد استفاده قرار می‌گیرد. این زبان امکانات بالایی برای مدیریت حافظه، کارایی بالا، و امکانات چندپارادیمی (مانند برنامه‌نویسی شیءگرا) فراهم می‌کند که در سراسر منابع کد بیت‌کوین شاهد آن هستیم. اما عامل ناراحتی او، مصرف انرژی بالا ممکن است که به علت نحوه استفاده یا پیاده‌سازی خاص از زبان و ابزارهای مرتبط با آن باشد و نه ضعف اساسی زبان سی‌پلاس‌پلاس، چرا که این زبان یکی از نام‌‌دار‌ترین زبان‌های است که مصرف انرژی و منابع را به بهترین حالت ممکن می‌توان در آن مدیریت کرد، از طرفی در صورت پیاده‌سازی نه چندان مطلوب کد‌ها، ممکن است نتیجهٔ عکس بدهد. در واقع معتقد است ممکن است کد‌نویسی بهینه‌ای صورت نگیرد و منجر به مصرف نسبتاً بالایی داشته باشد. وقتی ساتوشی بیت‌کوین را نوشت، او به‌طور ضروری پیش‌بینی نکرد که مسابقه‌ای که به وجود آمد باعث ساخت دستگاه‌های ASIC ماینینگ خواهد شد. در واقع، در صفحهٔ سفید اصلی بیت‌کوین که تنها 9 صفحه است، ساتوشی کلمه CPU را به مجموع 10 بار اشاره کرد. مصرف انرژی کنونی بیت‌کوین کمتر بود اگر ماینینگ به شکلی انجام می‌شد که ساتوشی پیش‌بینی کرده بود. حتی ساتوشی نیز از همان سرنوشتی که استرواستروپ هشدار داد: عدم کنترل بر نحوه استفاده از ابداع خود در آینده، مصون نبود. احتمالاً ساتوشی هم پیش‌بینی نکرده بود که بیت‌کوین در میان مجرمان نیز استفاده خواهد شد. اگرچه ممکن بوده باشد که در یک دوره زمانی بیت‌کوین محبوبیت زیادی در میان تجار مواد مخدر داشته باشد، اما مونرو به عنوان رمزارز انتخابی در میان بسیاری از گروه‌های جرمی ظاهر شده است. فعالیت‌های بشر که در مقیاس بزرگ بر محیط زیست تأثیر منفی می‌گذارند، زیاد است. بنابراین، هیچ توجیه منطقی برای اختصاص به‌طور خاص به ماینینگ بیت‌کوین وجود ندارد، به‌ویژه زمانی که مزیت مثبت آن به حداکثر است. اختصاص مصرف انرژی به ماینینگ رمزارز به‌منظور ایجاد و حفظ یک سیستم همتا به منظور تبادل مالی، یک کار کارآمد است چرا که دقیقاً همان چیزی است که برای حذف واسطه‌های غیرضروری و غیرتکنولوژیکی لازم است: واسطه‌هایی که روز آن‌ها نهایتاً فرا رسیده است. به طور کلی، ارزیابی یک زبان برنامه‌نویسی باید با توجه به نیازها و شرایط پروژه‌ها صورت گیرد. سی‌پلاس‌پلاس در بسیاری از مواقع یک انتخاب عالی است و اگرچه ممکن است برخی نقدهایی وجود داشته باشد، اما این نقدها به طور کلی به عنوان چالش‌ها و به چشم‌گیرترین قابلیت‌های این زبان می‌توانند مطرح شوند. نتیجهٔ نهایی زبان برنامه‌نویسی سی‌پلاس‌پلاس احتمالاً محبوب‌ترین زبان برنامه‌نویسی در دنیای توسعه نرم‌افزار است. توسعه بلاکچین نیز شامل کدنویسی است و برخی از بلاکچین‌ها مانند شبکه بیت‌کوین از سی‌پلاس‌پلاس به عنوان زبان برنامه‌نویسی خود استفاده می‌کنند. ساتوشی ناکاموتو، خالق بیت‌کوین، این زبان را به دلیل امنیت و قابلیت مدیریت منابع تراکنش‌ها و عملیات قراردادهای هوشمند انتخاب کرد. به علاوه، این زبان به توسعه‌دهندگان امکان ادغام وظایف موازی و غیرموازی را به صورت بی‌نقص فراهم می‌کند. مصرف بهینهٔ منابع و رعایت موضوع انرژی سبز مهم است؛ همچنین، این زبان به‌طور منظم به‌روزرسانی می‌شود و ابزارهای تجزیه و تحلیل و اشکال‌زدائی متنوعی دارد که همگی به بهبود عملکرد آن کمک می‌کنند. نگاه به بهترین مزایای زبان در بلاکچین، به همه اجازه می‌دهد که درک کنند چرا ساتوشی ناکاموتو این زبان را در ایجاد بلاکچین بیت‌کوین انتخاب کرد. ایجاد بلاک‌چین ناکاموتو یکی از پربارترین اختراعات فناوری مالی زمان ما را ایجاد کرد که شفافیت، تمرکززدایی و ماندگاری تراکنش ها و داده ها را تقویت کرد. ارز متمرکز بر بلاک‌چین نیز همچنان پر استفاده ترین، قابل اعتمادترین، ارز دیجیتال پرسود و چشم انداز سرمایه گذاری است و در پشت ساخت این فناوری غول زبان‌های برنامه‌نویسی آن را به بهترین نوع خود تبدیل و در همین راستا در مسیر توسعه و پیشرفت هدایت می‌کند.
  5. کامبیز اسدزاده

    این موضوع رو بررسی کنید:
  6. کامبیز اسدزاده

    درود، خب خطاها چی هستن؟
  7. کتابخانهٔ Boost: یک راهکار قدرتمند برای توسعهٔ برنامه‌های سی‌پلاس‌پلاس مقدمه کتابخانهٔ Boost یکی از مهم‌ترین ابزارها در دنیای برنامه‌نویسی سی‌پلاس‌پلاس است. این کتابخانه کاملاً رایگان بوده و مجموعه‌ای گسترده از کتابخانه‌ها و ابزارهای مفید برای توسعه‌دهندگان این زبان فراهم می‌کند. در این مقاله، به بررسی ویژگی‌ها، اهمیت و کاربرد کتابخانهٔ Boost در سی‌پلاس‌پلاس می‌پردازیم. ۱. ویژگی‌های کتابخانهٔ Boost کتابخانهٔ Boost دارای ویژگی‌های فراوانی است که آن را از سایر کتابخانه‌ها متمایز می‌کند. به برخی از این ویژگی‌ها در زیر اشاره خواهیم کرد: الف. تعداد زیادی ابزار و کتابخانه Boost شامل تعداد زیادی از کتابخانه‌ها و ابزارهای مفید است که برای تسهیل و افزایش کارایی در توسعهٔ نرم‌افزارهای سی‌پلاس‌پلاس به کار می‌روند. برخی از این کتابخانه‌ها شامل: کتابخانهٔ Boost.Filesystem: برای مدیریت فایل‌ها و دایرکتوری‌ها در سیستم عامل استفاده می‌شود. کتابخانهٔ Boost.Thread: برای پشتیبانی از نخ‌ها (Thread) و همزمان‌سازی استفاده می‌شود. کتابخانهٔ Boost.Regex: برای پردازش و مدیریت عبارات باقاعده (Regular Expressions) به کار می‌رود. ب. پشتیبانی از استانداردهای مدرن Boost به خوبی استانداردهای مدرن سی‌پلاس‌پلاس را پشتیبانی می‌کند. این کتابخانه ابزارها و قابلیت‌هایی ارائه می‌دهد که توسعه‌دهندگان را در استفاده از قابلیت‌های جدید و بهبود‌یافتهٔ زبان کمک می‌کند. با استفاده از Boost، می‌توانید از استانداردهای مدرن مانند C++11 و C++14 بهره‌برداری کنید و کدهای بهتری بنویسید. ۲. اهمیت Boost برای توسعهٔ سی‌پلاس‌پلاس کتابخانهٔ Boost اهمیت فراوانی در توسعهٔ سی‌پلاس‌پلاس دارد. به دلیل وجود ابزارها و کتابخانه‌های متنوع، Boost به توسعه‌دهندگان این زبان کمک می‌کند تا برنامه‌های قدرتمندی را با سرعت و کارایی بالا ایجاد کنند. همچنین، استفاده از Boost باعث می‌شود که کد نوشته شده توسط توسعه‌دهندگان با استانداردهای مدرن و قابلیت‌های بهبودیافتهٔ زبان همخوانی داشته باشد. ۳. کاربرد کتابخانهٔ Boost در سی‌پلاس‌پلاس کتابخانهٔ Boost در سی‌پلاس‌پلاس در بسیاری از زمینه‌ها کاربرد دارد. در ادامه به برخی از کاربردهای این کتابخانه می‌پردازیم: الف. توسعهٔ برنامه‌های شبکه Boost ابزارها و کتابخانه‌های قدرتمندی برای توسعهٔ برنامه‌های شبکه در سی‌پلاس‌پلاس فراهم می‌کند. از طریق Boost.Asio می‌توانید به راحتی بر نامه‌هایی با استفاده از پروتکل‌های مختلف شبکه مانند TCP و UDP بنویسید و با سرعت و کارایی بالا با ارتباطات شبکه کار کنید. ب. پردازش و مدیریت رشته‌ها Boost.Regex ابزاری قدرتمند برای پردازش و مدیریت رشته‌ها در سی‌پلاس‌پلاس است. این کتابخانه امکان استفاده از عبارات باقاعده را فراهم می‌کند و کار با رشته‌ها را بسیار آسان می‌کند. با استفاده از Boost.Regex، می‌توانید الگوهای مورد نظر خود را در رشته‌ها جستجو کنید و اقدامات لازم را انجام دهید. ۴. مزایای استفاده از کتابخانهٔ Boost استفاده از کتابخانهٔ Boost در توسعهٔ پروژه‌های سی‌پلاس‌پلاس دارای مزایای بسیاری است. به دلیل ویژگی‌ها و قابلیت‌های فراوان این کتابخانه، می‌توانید از مزایای زیر بهره‌برداری کنید: الف. افزایش کارایی و سرعت کتابخانهٔ Boost ابزارها و الگوریتم‌هایی را ارائه می‌دهد که می‌تواند عملکرد و کارایی برنامه‌ها را بهبود بخشید. با استفاده از این ابزارها، می‌توانید بهینه‌سازی‌های لازم را انجام داده و کارایی برنامه‌های خود را افزایش دهید. این موضوع بسیار مهم است زیرا کارایی و سرعت اجرای یک برنامه بر روی سیستم‌های حساس به زمان اهمیت بسیاری دارد. ب. پشتیبانی از چندپلتفرم کتابخانهٔ Boost بر روی چندپلتفرم قابل استفاده است و از این جهت بسیار مفید است. اگر برنامهٔ شما باید روی سیستم‌عامل‌های مختلف اجرا شود، Boost می‌تواند به شما در این مسئله کمک کند. شما می‌توانید از ابزارها و قابلیت‌های Boost استفاده کنید تا برنامهٔ خود را به طور مستقل از سیستم‌عامل مقصد اجرا کنید و از سهولت توسعه و نگهداری برخوردار شوید. ج. جامعیت و پایداری Boost یک کتابخانهٔ بسیار جامع و پایدار است. این به این معناست که شما می‌توانید به ابزارها و قابلیت‌های Boost برای پروژه‌های مختلفی با انواع نیازها و مشکلات بهره‌برداری کنید. این کتابخانه توسعه یافته و توسط جامعهٔ سی‌پلاس‌پلاس حمایت می‌شود، بنابراین می‌توانید از پشتیبانی و به‌روزرسانی‌های مداوم برخوردار شوید. ۵. کاربردهای کتابخانهٔ Boost کتابخانهٔ Boost به دلیل قابلیت‌ها و امکانات فراوان خود، در زمینه‌های مختلفی از جمله زیر استفاده می‌شود: الف. توسعهٔ برنامه‌های کاربردی Boost ابزارها و کتابخانه‌هایی را فراهم می‌کند که می‌تواند در توسعهٔ برنامه‌های کاربردی مختلف مفید باشد. مثلاً Boost.Asio برای برنامه‌نویسی شبکه، Boost.FileSystem برای کار با سیستم‌فایل و Boost.DateTime برای کار با زمان و تاریخ مورد استفاده قرار می‌گیرد. با استفاده از این ابزارها، می‌توانید برنامه‌های کاربردی پیچیده را با قابلیت‌های خاص و منحصربه‌فرد طراحی و پیاده‌سازی کنید. ب. توسعهٔ بسترهای نرم‌افزاری کتابخانهٔ Boost به عنوان یک بستر نرم‌افزاری مناسب برای توسعهٔ برنامه‌های کاربردی و تحت وب استفاده می‌شود. با استفاده از Boost، می‌توانید بسترهای نرم‌افزاری پویا و پایداری ایجاد کنید که قابلیت‌ها و خصوصیات منحصربه‌فردی داشته باشند. این کتابخانه شما را قادر می‌سازد تا بسترهای قابل گسترش، قابل تنظیم و با قابلیت انعطاف‌پذیری بالا را پیاده‌سازی کنید. ج. توسعهٔ بازی‌ها و گرافیک کامپیوتری Boost در زمینهٔ توسعهٔ بازی‌ها و گرافیک کامپیوتری نیز استفاده می‌شود. ابزارهایی مانند Boost.Geometry برای کار با هندسه و Boost.Graph برای تحلیل و پردازش گراف‌ها مورد استفاده قرار می‌گیرند. این ابزارها به توسعه‌دهندگان کمک می‌کنند تا الگوریتم‌های پیچیده را برای بازی‌ها و سیستم‌های گرافیکی پیاده‌سازی کنند و تجربهٔ کاربری بهتری را ارائه دهند. ۶.اهمیت کتابخانهٔ Boost کتابخانهٔ Boost در دنیای سی‌پلاس‌پلاس بسیار اهمیت دارد. استفاده از این کتابخانه می‌تواند توسعهٔ برنامه‌های شما را سریعتر، قابل اطمینان‌تر و کارآمدتر کند. با قابلیت‌ها و امکانات گستردهٔ Boost، می‌توانید در توسعهٔ نرم‌افزارهای پیچیده و با تعامل بالا بهترین عملکرد را به دست آورید. ۷. چگونه از کتابخانهٔ Boost بهره‌برداری کنیم؟ برای بهره‌برداری از کتابخانهٔ Boost و استفاده بهینه از قابلیت‌های آن، می‌توانید مراحل زیر را دنبال کنید: الف. نصب کتابخانه ابتدا باید کتابخانهٔ Boost را بر روی سیستم خود نصب کنید. می‌توانید نسخهٔ مناسب برای سیستم‌عامل خود را از وبسایت رسمی Boost دریافت کنید و طبق دستورالعمل‌های نصب آن را انجام دهید. ب. مستندات و منابع آموزشی بهتر است پیش از شروع استفاده از Boost، به مستندات رسمی آن مراجعه کنید. مستندات کتابخانه به شما راهنمایی دقیقی دربارهٔ ویژگی‌ها، توابع و کلاس‌های موجود در Boost ارائه می‌دهد. همچنین، می‌توانید از منابع آموزشی آنلاین و کتاب‌های مرجع موجود برای یادگیری عمیق‌تر از Boost استفاده کنید. ج. استفاده در پروژه‌ها با نصب کتابخانه و آشنایی با مستندات، می‌توانید Boost را در پروژه‌های خود استفاده کنید. در هر قسمت از پروژه که نیاز به قابلیت‌ها یا الگوریتم‌های خاصی دارید، می‌توانید به کتابخانهٔ Boost مراجعه کنید و از آن استفاده کنید. با استفاده از توابع و کلاس‌های Boost، می‌توانید کدهای کوتاهتر، بهینه‌تر و قابل نگهداری‌تری ایجاد کنید. ۸. بهترین استفاده از کتابخانهٔ Boost برای بهترین استفاده از کتابخانهٔ Boost، توصیه می‌شود: با استفاده از نسخهٔ مناسب Boost برای پروژه خود، به‌روزرسانی‌ها و بهبودهای ارائه شده را دنبال کنید. با دقت مستندات رسمی Boost کار کنید و قابلیت‌ها و توابع موجود را به‌خوبی بشناسید. از منابع آموزشی متنوع استفاده کنید تا مفاهیم و مباحث پیشرفته‌تر را بیاموزید. در صورت نیاز، از جامعهٔ سی‌پلاس‌پلاس و انجمن‌های مرتبط با Boost برای رفع سوالات و دریافت راهنمایی استفاده کنید. نتیجه‌گیری کتابخانهٔ Boost با ارائهٔ ابزارها و کتابخانه‌های مفید، اهمیت و کاربرد زیادی در توسعهٔ سی‌پلاس‌پلاس دارد. از ویژگی‌های برجستهٔ این کتابخانه می‌توان به تعداد زیادی ابزار و کتابخانه، پشتیبانی از استانداردهای مدرن و کاربردهای مختلف در برنامه‌نویسی اشاره کرد. با استفاده از Boost، توسعه‌دهندگان می‌توانند برنامه‌های قدرتمندی را با سرعت و کارایی بالا ایجاد کنند و از قابلیت‌های بهبودیافتهٔ زبان بهره‌برداری کنند. کتابخانهٔ Boost با ویژگی‌ها و قابلیت‌های منحصربه‌فرد خود، نقش بسیار مهمی در توسعهٔ پروژه‌های سی‌پلاس‌پلاس دارد. استفاده از این کتابخانه باعث می‌شود تا برنامه‌های قدرتمند، قابل اعتماد و با کارایی بالا ایجاد شوند. همچنین، Boost به توسعه‌دهندگان کمک می‌کند تا با استفاده از استانداردهای مدرن، بهترین نتایج را در توسعهٔ برنامه‌ها به دست آورند.
  8. با سلام و درود‌های فراوان بر شما دوست‌داران طراحی و توسعه، امروز نیاز دیدم یک توضیح در رابطه با تفاوت‌های عمدهٔ فناوری ساخت و توسعهٔ رابط‌کاربری در نرم‌افزار‌های تحت فریمورک کیوت ارائه کنم. در این مقاله من به دو سبک متفاوت با کارآیی و اهمیت آن‌ها مطابق با مستندات فریم‌ورک کیوت می‌پردازم و شما می‌توانید بر اساس نیازمندی و برداشت خود از آن، یکی از فناوری‌های لازم را انتخاب و ظاهر برنامهٔ خودتان را با آن آراسته کنید! رابط‌کاربری (UI) یکی از عوامل اصلی در جذب کاربران و بهبود تجربه‌‌کاربری (UX) است. یک طراحی صحیح و مناسب برای واسط‌کاربری می‌تواند کاربران را به نرم‌افزار شما جذب کند و به معنای واقعی کاربران را متقاعد کند که نرم‌افزار شما صحیح است و قابل استفاده، حتی اگر امر اصلی برنامه اجرای آن باشد. رابط‌کاربری مناسب، کاربران را به یادگیری آسان فرایند‌های نرم‌افزار و همچنین استفاده از آن ترغیب می‌کند. با طراحی یک واسط کاربری ساده و کاربر پسند، می‌توان زمان و هزینه‌ای برای آموزش کاربرانی که قرار است از نرم‌افزار شما استفاده کنند, صرفه جویی کرد. در نهایت، رابط‌کاربری نرم‌افزار ممکن است انگیزه‌های کاربران برای استفاده از نرم‌افزار شما را افزایش دهد. با انتخاب فوق‌العاده از کاغذ دیواری و فونت‌های جذاب، شما می‌توانید به تاثیر خوبی بر روی انگیزه‌های کاربران برای استفاده از نرم‌افزار خود داشته باشید. اهمیت رابط‌های کاربری مدرن و سنتی رابط‌کاربری سنتی، یک رابط‌کاربری ابتدائی است، که چندین دهه است به کار می‌رود. این سبک برای محیط‌های کاربردی نسبتاً پایدار و ساده‌تر معرفی شده است، با پنجره‌ها، دستورالعمل‌های پایه، معمول و منو‌‌های کلاسیک. اما اخیراً، رابط‌های کاربری مدرن، تلاش کرده‌اند تا به کاربرانی که حوصله‌ٔ کار با رابط‌کاربری سنتی را ندارند، ارائه شوند چرا که نیاز به تعامل و تجربه‌کاری بهتر بیشتر و بیشتر می‌شود. این رابط‌ها، با استفاده از طراحی مدرن، صفحات پویا، و مفهوم سرعت، زیبایی و حتی تحرک مناسب، می‌خواهند توانایی شما را در مدیریت محیط‌کاری (کار با نرم‌افزار) افزایش دهند. بیشتر رابط‌های کاربری مدرن، به کاربران محیط کاری تمیز و منظم، صفحه اصلی متحرک، آیکون های جذاب و فهرست منوی منظم، نوع قلم و اندازهٔ مناسب و جذاب را ارائه می‌دهد تا با اشتیاق بیشتری از کار با محیط مورد نظر لذت ببرید. در این سند، تفاوت بین Widgets Qt و Qt Quick و نحوهٔ انتخاب مناسب برای نیازهای برنامه خود را توضیح خواهیم داد. قبل از اینکه به دلایلی بپردازیم که چرا شما ممکن است بخواهید Widgets Qt را به Qt Quick یا برعکس انتخاب کنید، سپس شروع به بررسی آنچه که هر کدام دقیقاً ارائه می‌دهند و در چه شرایطی می‌توانید از آنها استفاده کنید نیز خواهیم داشت. راه‌کار‌های فریم‌ورک Qt برای طراحی رابط‌کاربری این فریم‌ورک دارای چندین فناوری برای ایجاد رابط‌کاربری است. در حالی که می‌توان این فناوری‌های مختلف را در صورت نیاز ترکیب و مطابقت داد، یک رویکرد اغلب برای نوع خاصی از رابط کاربری مناسب‌تر از سایرین است. Qt Creator مثال خوبی از برنامه‌ای است که ویجت‌های سنتی Qt را با Qt Quick ترکیب می‌کند. Qt Widgets اساس رابط‌کاربری را تشکیل می‌دهند، در حالی که Qt Quick به عنوان مثال برای اجرای حالت خوش آمدگویی استفاده می شود. بخش‌های زیر معرفی مختصری از فناوری‌های موجود برای ایجاد رابط کاربری و جدول مقایسه‌ای برای کمک به انتخاب بهترین فناوری مناسب ارائه می‌دهند. دربارهٔ Qt Widget (کیوت ویجت) ماژول Qt Widgets مجموعه‌ای از عناصر رابط‌کاربری را برای ایجاد رابط‌های کاربری کلاسیک به سبکِ پیش‌فرضِ دسکتاپ فراهم می‌کند. کلاس QWidget قابلیت اولیه برای رندر کردن (ساخت) روی صفحه و مدیریت رویدادهای ورودی کاربر را فراهم می‌کند. تمام عناصر UI که Qt ارائه می‌کند یا زیر کلاس‌های QWidget هستند یا در ارتباط با یک زیر کلاس QWidget استفاده می‌شوند. ایجاد ویجت‌های سفارشی با زیر کلاس QWidget یا یک زیر کلاس مناسب و پیاده‌سازی مجدد کنترل کننده رویداد مجازی انجام می‌شود. سبک‌ها (پوسته‌ها/ظاهر) سبک‌ها به نمایندگی از ویجت‌ها طراحی می‌شوند و ظاهر و احساس یک رابط‌کاربری گرافیکی را دربر می‌گیرند. ویجت‌های داخلی Qt از کلاس QStyle برای انجام تقریباً تمام طراحی‌های خود استفاده می‌کنند و اطمینان حاصل می‌کنند که دقیقاً شبیه ویجت‌های بومی معادل هستند که در زیر تصاویر مربوط به ظاهر پیش‌فرض سیستم‌عامل‌های ویندوز، لینوکس و مک هستیم. به طور کلی، Qt Style Sheets مکانیزم قدرتمندی است که به شما امکان می‌دهد ظاهر ویجت‌ها را سفارشی کنید، علاوه بر آنچه که قبلاً با زیر کلاس‌بندی QStyle امکان‌پذیر است. لایه‌بندی‌ها (چیدمان) چیدمان‌ها روشی ظریف و انعطاف پذیر برای مرتب کردن خودکار ویجت های کودک در ظرف خود هستند. هر ویجت مورد نیاز اندازه خود را از طریق خصوصیات sizeHint و sizePolicy به چیدمان گزارش می‌دهد و طرح‌بندی فضای موجود را بر این اساس توزیع می‌کند. محیط Qt Designer یک ابزار قدرتمند برای ایجاد تعاملی و چیدمان ویجت‌ها در طرح‌بندی است. کلاس‌های Model/View معماری model/view کلاس‌هایی را ارائه می‌دهد که نحوه ارائه داده‌ها به کاربر را مدیریت می‌کنند. برنامه‌های مبتنی بر داده که از فهرست‌ها و جداول استفاده می‌کنند، به گونه‌ای ساختار یافته‌اند که داده‌ها و مشاهده را با استفاده از مدل‌ها، نماها و نمایندگان جدا کنند. محیط توسعهٔ Qt Creator و بخش Qt Designer ویرایشگر کد پیشرفته Qt Creator به شما امکان می‌دهد نرم‌افزار را به زبان‌های C++، QML، جاوا اسکریپت، پایتون و سایر زبان‌ها بنویسید. این ویژگی تکمیل کد، برجسته سازی نحو، refactoring است و دارای اسناد داخلی در نوک انگشتان شما است. دربارهٔ کیوت کوئیک (Qt Quick) ماژول Qt Quick کتابخانهٔ استاندارد برای نوشتن برنامه‌‌های کاربردی QML است. در حالی که ماژول Qt QML موتور QML و زیرساخت زبان را فراهم می‌کند، ماژول Qt Quick تمام انواع اساسی لازم برای ایجاد رابط‌کاربری با QML را ارائه می‌دهد. در واقع یک بوم بصری را ارائه می‌کند و شامل انواعی برای ایجاد و متحرک کردن اجزای بصری، دریافت ورودی کاربر، ایجاد مدل‌ها و نماهای داده‌ها و نمونه‌سازی با تأخیر شیء است. ماژول Qt Quick نیز یک API QML ارائه می‌کند که انواع QML را برای ایجاد رابط‌های کاربری با زبان QML فراهم می‌کند و هم یک رابط‌برنامه‌نویسی (API) از ++C برای گسترش برنامه‌های QML با کد ++C ارائه می‌کند. این یک مزیت بزرگ است که به شما اجازه می‌دهد رابط‌های مبتنی بر قدرت سی++ را به خوبی ارائه کنید. پوستهٔ پیش‌فرض (Default) تا کیوت ۵ و پوستهٔ پایه (Basic) از کیوت ۶ به بعد. سبک پیش فرض یک سبک همه جانبه ساده و سَبُک است که حداکثر عملکرد را برای کنترل های سریع Qt ارائه می دهد. پوستهٔ فیوژن (Fusion) سبک Fusion یک سبک پلتفرم آگنوستیک است که ظاهری بی‌نظیر دسک‌تاپ را برای کنترل‌های کیوت کوئیک ارائه می‌دهد. پوستهٔ ایمَجین (Imagine) سبک Imagine بر اساس دارایی‌های تصویر است. این سبک دارای مجموعه‌ای پیش‌فرض از تصاویر است که به راحتی با ارائه یک فهرست حاوی تصاویر با استفاده از یک قرارداد نامگذاری از پیش تعریف شده قابل تغییر است. پوستهٔ مک‌او‌اِس (macOS) از کیوت ۶ به بعد. سبک macOS یک سبک بومی برای macOS است. پوستهٔ آی‌او‌اِس (iOS) از کیوت ۶ به بعد. سبک iOS یک سبک بومی برای iOS است. پوستهٔ متریال (Material) سبک Material، طراحی جذابی را بر اساس دستورالعمل‌های طراحی متریال Google ارائه می‌کند، اما به منابع سیستم بیشتری نسبت به سبک پیش‌فرض نیاز دارد. پوستهٔ یونیورسال (Universal) سبک Universal طراحی جذابی را بر اساس دستورالعمل‌های طراحی جهانی مایکروسافت ارائه می‌کند، اما به منابع سیستم بیشتری نسبت به سبک پیش‌فرض نیاز دارد. پوستهٔ ویندوز (Windows) از کیوت ۶ به بعد. سبک Windows یک سبک بومی برای Windows است. اگر هیچ سبکی به صراحت تنظیم نشده باشد، یک سبک پیش فرض استفاده خواهد شد. سبکی که استفاده می‌شود به سیستم‌عامل بستگی دارد: سیستم‌عامل اندروید: Material Style سیستم‌عامل آی‌او‌اِس: iOS Style سیستم‌عامل لینوکس: Fusion Style سیستم‌عامل مک‌او‌اِس: macOS Style سیستم‌عامل ویندوز: Windows Style انتخاب سبک در زمان کامپایل انتخاب سبک زمان کامپایل راهی برای تعیین یک سبک برای استفاده با وارد کردن آن در QML است. به عنوان مثال، برای وارد کردن سبک Material: import QtQuick.Controls.Material ApplicationWindow { // ... } انتخاب سبک در زمان اجرا انتخاب سبک زمان اجرا راهی برای تعیین یک سبک برای استفاده با وارد کردن QtQuick.Controls است: import QtQuick.Controls افزونهٔ QtQuick.Controls استایل و استایل بازگشتی را که در زمان اجرا تنظیم شده‌اند از طریق یکی از روش‌های زیر وارد می‌کند: دستورQQuickStyle::setStyle() The -style آرگومان خط فرمات QT_QUICK_CONTROLS_STYLE متغیر‌های محای qtquickcontrols2.conf پیکربندی از طریف فایل اولویت این رویکردها به ترتیبی است که فهرست شده‌اند، از بالاترین به پایین‌ترین. یعنی استفاده از QQuickStyle برای تنظیم استایل همیشه بر استفاده از آرگومان خط فرمان اولویت دارد. برای اجرای یک برنامه با یک سبک خاص، یا با استفاده از QQuickStyle در ++C، پوسته را پیکربندی کنید، یک آرگومان خط فرمان را ارسال کنید، یا یک متغیر محیطی را تنظیم کنید. روش دیگر، سبک ترجیحی و ویژگی‌های خاص سبک را می‌توان در یک فایل پیکربندی مشخص کرد. اولویت این رویکردها به ترتیبی است که در زیر فهرست شده‌اند، از بالاترین به پایین‌ترین. یعنی استفاده از QQuickStyle برای تنظیم استایل همیشه بر استفاده از آرگومان خط فرمان اولویت دارد. استفاده از Qt Quick Style در ++C رابط‌های QQuickStyle C++ API پیکربندی یک سبک خاص را ارائه می‌کند. مثال زیر یک برنامه Qt Quick Controls را با سبک Material اجرا می‌کند: QQuickStyle::setStyle("Material"); استفاده از روش آرگومان‌های خط فرمان ارسال آرگومان خط فرمان-style راه مناسبی برای آزمایش سبک‌های مختلف است. این روش بر سایر روش های ذکر شده در زیر ارجحیت دارد. مثال زیر یک برنامه Qt Quick Controls را با سبک Material اجرا می‌کند: ./app -style material استفاده از روش متغیر‌های محیطی تنظیم متغیر محیطی QT_QUICK_CONTROLS_STYLE را می‌توان برای تنظیم ترجیح سبک در سراسر سیستم استفاده کرد که بر فایل پیکربندی ذکر شده در زیر ارجحیت دارد. مثال زیر یک برنامه Qt Quick Controls را با سبک جهانی اجرا می‌کند: QT_QUICK_CONTROLS_STYLE=universal ./app استفاده از روش پیکربندی فایل کنترل‌های کیوت کوئیک، از یک فایل پیکربندی خاص پشتیبانی می‌کند، :/qtquickcontrols2.conf، که در منابع یک برنامه تعبیه شده است. فایل پیکربندی می‌تواند سبک ترجیحی (ممکن است با یکی از روش‌هایی که قبلا توضیح داده شد لغو شود) و ویژگی‌های خاص سبک را مشخص کند. مثال زیر مشخص می کند که سبک ترجیحی سبک Material است. [Controls] Style=Material سفارشی‌سازی کنترل‌های کیوت کوئیک کنترل کیوت کوئیک از یک سلسله مراتب (درخت) از آیتم‌ها تشکیل شده است. به منظور ارائه ظاهر و احساس سفارشی، پیاده‌سازی پیش‌فرض QML هر آیتم را می‌توان با یک سفارشی جایگزین کرد. گاهی اوقات شما می‌خواهید برای یک بخش خاص از UI خود یک ظاهر «یکباره» ایجاد کنید و در هر جای دیگر از یک سبک کامل استفاده کنید. شاید از سبکی که استفاده می‌کنید راضی باشید، اما دکمه خاصی وجود دارد که اهمیت خاصی دارد. پشتیبانی از High-DPI در کیوت کوئیک کنترل‌های کیوت کوئیک، از مقیاس‌گذاری چند-سکویی با DPI (نقطه در اینچ) بالا که در Qt 5.6 معرفی شده است، پشتیبانی می‌کند. این ویژگی انتخابی است و می‌توان آن را با تنظیم ویژگی برنامه Qt::AA_EnableHighDpiScaling در ++C قبل از ساخت QGuiApplication فعال کرد: #include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // <-- QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } محیط طراحی اختصاصی Qt Design Studio فرآیند توسعه خود را با پر کردن شکاف بین طراحان و توسعه‌دهندگان متحول کنید تا دیدگاه‌های طراحی خود را به رابط های کاربری آماده تولید تبدیل کنید. طراحی‌های رابط‌کاربری را با ابزارهای طراحی مانند Figma، Adobe XD یا Adobe Photoshop ایجاد کنید. آنها را به استودیوی طراحی Qt وارد کنید، جایی که کد به طور خودکار تولید شده و آماده استفاده توسط توسعه‌دهندگان است. تعاملات و رفتارهای پویا را شبیه‌سازی و تایید کنید. هر چیزی که در استودیوی طراحی Qt ساخته شده است ذاتاً کراس پلتفرم است و می‌تواند در هر سخت‌افزار یا محیط سیستم‌عاملی کامپایل شود. وقتی در مورد ایجاد رابط‌کاربری صحبت می‌کنیم، فقط در مورد ایجاد یک ماکت با دارایی‌های موجود صحبت نمی‌کنیم. با Qt Design Studio، دارایی‌های شما تبدیل به یک ترکیب رابط‌کاربری می‌شود که آماده عملکرد است. تفاوت‌های عمدهٔ Qt Widgets طراحی با این ماژول فقط بر پایهٔ زبان‌های برنامه‌نویسی ++C و Python در امکان‌پذیر است. .سبک و ظاهر بومی در پلتفرم‌های دسکتاپ اما نه در پلتفرم‌های موبایل. امکان سفارشی شدن را دارد. به بک‌اند بومی جهت ساخت نیاز ندارد. می‌تواند در مواقع لزوم از رابط‌های برنامه‌نویسی بومی بک‌اندی هر پلتفرم استفاده کند. سبک پایه را ارائه می‌کند، روان نیست، اما امکان تعریف انیمیشن را ارائه می‌کند. به واسطهٔ زیر کلاس‌ها یا کلاس‌های سفارشی خودتان می‌توانید رفتار‌های ویجت‌ را باز تعریف کنید. محیط اختصاصی طراحی و توسعهٔ Qt Designer تفاوت‌های عمدهٔ Qt Quick طراحی با این ماژول به صورت پایه به واسطهٔ QML امکان‌پذیر است. هرچند هنوز هم برخی از نیازمندی‌ها به واسطهٔ ++C و Python انجام می‌شود. شما می‌توانید ماژول‌ها و کامپوننت‌های سفارشی خوبی به واسطهٔ ++C برای QML طراحی کنید. ظاهر کاربری بومی تحت ماژول Qt Quick Controls از نسل کیوت ۶ به بعد ممکن شده است. تطبیق و دریافت اطلاعات پوسته برای اندروید در زمان نیاز ممکن است. به بک‌اند بومی و پس‌زمینه وابسته است. همچنین می‌توانید ایتم‌های خود را به صورت مستقیم با بک‌اند بومی ارائه کنید. می‌توانید پوستهٔ روان و جذابی را تعریف کنید. پیاده‌سازی انیمیشن‌ها و جلوه‌های بصری پیچیده بسیار ساده قابل پیاده‌سازی شدن است. جلوه‌های گرافیکی به راحتی قابل تعریف هستند. امکان سفارشی‌سازی رفتار‌های آیتم و کنترل‌ها وجود دارد. به واسطهٔ گسترش و یا ساخت کامپوننت‌های سفارشی خود بر اساس انواع موجود در Qt Quick. علاوه بر پشتیبانی از محیط Qt Designer، به محیط اختصاصی و پیشرفتهٔ طراحی و توسعهٔ Qt Design Studio مجهز است. چه زمانی باید یکی از این فناوری‌ها را به دیگری ترجیح دهیم؟ Qt Widgets اگر شما نیاز به یک رابط‌کاربری ساده و سریع نیاز دارید. اگر نمی‌خواهید با JavaScript سرو کار داشته باشید. Qt Quick زمانی که می‌خواهید رابط‌های کاربری جذاب و خلاقانه تولید کنید. زمانی که می‌خواهید برنامهٔ خود را برای موبایل و دستگاه‌های جاسازی شده (امبد) ارائه کنید. وقتی هدفتان ساخت نرم‌افزار‌های چند-سکویی باشد. زمانی که می‌خواهید بیشترین جذابیت و کارآیی را از نظر UI و UX ارائه کنید. آشنایی با زیرساخت RHI و کارآیی دو فناوری کیوت ویجت و کیوت کوئیک بسیاری از کاربران با توجه به کد‌های سی++ در کیوت ویجت، بر این باورند که ساخت و توسعهٔ رابط‌های کاربری با Qt Widgets عموماً سریع‌تر و از کارآیی بهتری برخوردار است. این حقیقت در قبل از زمان فناوری جدید از نسل کیوت کوئیک اعتبار بسیاری داشت، اما با توجه به توسعهٔ زیرساخت‌های کیوت در نسل‌های ۵.۱۵ و ۶ به بعد، تمامی فرایند رندرینگ به لطف کد‌های سی‌پلاس‌پلاس به صورت بومی تحت معماری RHI انجام می‌شوند و این مسأله دیگر حائز اهمیت نیست، مگر این‌که دلایل شما برای انتخاب کیوت ویجت صرفاً دسترسی ساخت به رابط‌کاربری ساده‌تر و عدم اهمیت داشتن سبکِ نوین باشد. زیرساخت QRhi، یک رابط سخت‌افزاری رندر Qt، انتزاع گرافیکی داخلی Qt است که در آن API‌های سه بعدی مانند OpenGL، Vulkan، Metal و Direct 3D درگیر هستند. در مقایسه با 5.15، پیشرفت‌های اصلی در نسخه 6.0، اصلاحات پولیش زیاد اینجا و آنجا و مهمتر از همه، مجموعه بزرگی از بهینه‌سازی عملکرد است. این بهینه سازی به طور کامل به صورت بومی و رابط‌های برنامه‌نویسی ترکیبی با ++C پیاده‌سازی شده است و کارآیی خروجی در تولید رابط‌های خلاقانه، جلوه‌های بصری ۲ و ۳ بعدی بسیار عالی خواهد بود. سخن پایانی ساخت و توسعهٔ یک رابط‌کاربری امروزه یکی از مهم‌ترین معیار‌های سنجش کیفی نرم‌افزار در سمت کاربر است، اگر این موضوع برای شما اهمیت بسیار دارد، قطعاً باید به روش‌های اختصاصی در طراحی سوق پیدا کنید. در غیر این صورت نیاز به کد‌نویسی بیشتر، درک و بازنویسی انتزاع‌های فراوان در سمت کد‌های خام به واسطهٔ Qt Widgets بسیار خسته کننده خواهد بود.
  9. شرکت اینتل یک کیت توسعه نرم‌افزار آزمایشی کوانتومی با نام Quantum SDK را منتشر کرد! این کیت یک سری ابزار و روش‌های برنامه‌نویسی را در اختیار توسعه‌دهندگان قرار می‌دهد که امکان برنامه‌نویسی الگوریتم‌های کوانتومی را در یک شبیه‌سازی ممکن می‌کند. این کیت از زبان برنامه‌نویسی ++C و کامپایلر LLVM برای برنامه‌نویسی الگوریتم‌های کوانتومی استفاده می‌کند و به سادگی می‌تواند با برنامه‌های C و ++C و پایتون به کار برده شود. این کیت، به نوعی باعث بزرگ شدن جامعه‌ٔ توسعه‌دهندگانی می‌شود که در زمینه‌ٔ کامپیوترهای کوانتومی فعالیت می‌کنند. این عکس نشان می‌دهد که شرکت اینتل، و افرادی که در آن کار می‌کنند، با استفاده از یک دستگاه پردازشی ۳۰۰ میلی‌متری، وافرین بر روی یک وافر کیوبیتی (بخشی از یک صفحه اتصال کوانتومی) سیلیسیوم بر روی یک ورقه کوچک انجام داده‌اند. – آن ماتسورا، مدیر برنامه‌های کاربردی و معماری کوانتومی، آزمایشگاه‌های اینتل درباره‌ی Intel Quantum SDK 1.0: نسخه‌ٔ 1.0 این SDK، شامل یک رابط برنامه‌نویسی مبتنی بر سی‌پلاس‌پلاس است که به برنامه‌نویسان کلاسیکی، زبان برنامه‌نویسی که با آن آشنایی دارند، را ارائه می‌دهد و امکان همکاری بین آن‌ها و برنامه‌نویسان کوانتومی را فراهم می‌کند. این کیت نیز، یک محیط اجرایی کوانتومی بهینه‌سازی شده برای اجرای الگوریتم‌های کوانتومی-کلاسیکی هیبریدی دارد. توسعه‌دهندگان می‌توانند از دو محیط مختلف برای شبیه‌سازی کیوبیت‌ها استفاده کنند، یکی برای نمایش بیشتر تعدادی کیوبیت‌های عمومی و دیگری، برای شبیه‌سازی سخت‌افزار کیوبیتی اینتل. محیط اولیه، یک شبیه‌ساز کیوبیت عمومی بسیار عالی با کد منبع باز به نام Intel® Quantum Simulator (IQS) می‌باشد که برای 32 کیوبیت در یک گره و بیش از 40 کیوبیت در چندین گره، توانایی دارد. محیط دوم نیز با شبیه‌سازی سخت‌افزار کیوبیتی اینتل، شبیه‌سازی کوچک مدل کیوبیت‌های گرداننده اسپین سیلیکونی اینتل را فراهم می‌کند. کیوبیت‌های اینتل، از تخصص شرکت در تولید ترانزیستور سیلیکونی برای ساخت کامپیوترهای کوانتومی مقیاس گسترده استفاده می‌کنند. تحقیقات کوانتومی اینتل از دستگاه‌های کیوبیتی تا معماری سخت‌افزار کلی، معماری نرم‌افزار و برنامه‌ها را پوشش می‌دهد. Intel Quantum SDK یک کامپیوتر کوانتومی کامل در شبیه‌سازی است که همچنین قادر به اتصال به سخت‌افزار کوانتومی اینتل، از جمله چیپ کنترل Horse Ridge II و چیپ کیوبیت گرداننده اسپین اینتل است که بزودی در اختیار عموم قرار خواهد گرفت. کیت توسعه‌ٔ کوانتومی اینتل، به توسعه‌دهندگان این امکان را می‌دهد که انتخاب کنند کدام یک از دو محیط موردنیاز برای شبیه‌سازی کیوبیت‌ها استفاده شود: شبیه‌ساز بسیار عالی و با کد منبع باز کیوبیت عمومی، شبیه‌ساز کوانتومی اینتل (Intel Quantum Simulator) محیط هدف که سخت‌افزار کیوبیتی اینتل را شبیه‌سازی می‌کند و به شبیه‌سازی مدل کوچک کیوبیت‌های گرداننده اسپین سیلیکون اینتل امکان می‌دهد. اعلام شده که شرکت اینتل، متعهد به پیشروی در حوزه‌ٔ کامپیوترهای کوانتومی است و از جمله اینترنت از همه جا به عنوان یک روش برای جذب جامعه‌ٔ توسعه‌دهندگان می‌باشد. کاربران بتا این کیت، در حال بررسی انواع موارد مثل دینامیک سیالات، فیزیک نجوم وطراحی مواد هستند. تحقیقات کوانتومی اینتل از دستگاه‌های کیوبیتی تا معماری سخت‌افزار کلی، کنترل و معماری نرم‌افزار و برنامه‌ها را پوشش می‌دهد.
  10. کامبیز اسدزاده

    جزئیات، به‌روز رسانی‌ها و ویژگی‌های 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 نگهداری می‌شوند). به این ترتیب، ما از خطرات ارجاع به اشاره به محدوده‌های خارج از داده ها به دلیل دستکاری در آرایه، محافظت می‌کنیم.
  11. کامبیز اسدزاده

    مروری بر پنج اصلِ شیء‌گرایی با عنوان SOLID

    یکی از مواردی که در مباحث شیء‌گرایی مهم هستن با عنوان اصول SOLID شناخته می‌شه که شاید خیلی‌ها شنیده باشند. واژهٔ SOLID برگرفته شده از پنج اصلِ زیر است: S - Single-responsiblity Principle O - Open-closed Principle L - Liskov Substitution Principle I - Interface Segregation Principle D - Dependency Inversion Principle برای پیاده‌سازی SOLID در C++20، می‌توانید از ویژگی‌های زبان استفاده کنید. برای مثال: برای پیاده‌سازی SRP، می‌توانید از کلاس‌های ساختاری (Structs) و کلاس‌ها و متد‌ها که فقط یک وظیفه دارند، استفاده کنید. برای پیاده‌سازی OCP، می‌توانید از الگوی Visitor و Strategy استفاده کنید. این باعث می‌شود که کلاس‌های شما قابلیت بسته‌بودن (Close) و در عین حال قابلیت گسترش ‌(Open) را داشته باشند. برای پیاده‌سازی LSP، می‌توانید از وراثت، کلاس‌های پایه (Base classes) و کلاس‌های مشتق (Derived classes) استفاده کنید و مطمئن شوید که اصول وراثت رعایت شده است. برای پیاده‌سازی ISP، می‌توانید از الگوی Interface استفاده کنید که به شما امکان می‌دهد که کلاس‌ها فقط به آن قسمت‌هایی از یک Interface نیاز دارند که به آن‌ها لازم است و از بقیه صرف نظر کنند. برای پیاده‌سازی DIP، می‌توانید از Dependency Injection استفاده کنید که به شما این امکان را می‌دهد که از تمام وابستگی‌های بین کلاس‌ها جدا شده و به‌صورت جداگانه به هم پیوندید، به‌طوری‌که تغییر در یک کلاس اثرات اصلی بر سایر کلاس‌ها نداشته باشد. اصلِ اول مربوط به اصل Single-Responsibility Principle یا همان SRP است. این اصل مشخص می‌کند که کلاس‌های شما باید هر کدامشان فقط و فقط باید یک وظیفهٔ مشخص داشته باشند و نه بیشتر! برای پیاده‌سازی SRP بنابراین، اصلِ SRP در شیء‌گرایی به معنی این است که هر کلاس و متد باید فقط یک مسئولیت یا وظیفه را برعهده داشته باشد. این یعنی که هر کلاس فقط باید یک مورد از نرم‌افزار را انجام دهد و تغییر در آن، صرفا برای اعمال تغییرات در آن مورد خاص یا در راستای بهبود مسئولیتش باشد. با رعایت اصل SRP، کدها به راحتی قابل نگهداری، توسعه و آزمایش خواهند بود؛ زیرا هر قطعه از کد فقط برای انجام کار خاص خود طراحی شده است و هیچ گونه وظیفه‌ای به کلاس اضافه نشده است. این نه تنها باعث بهبود خوانایی و قابلیتِ پیش‌بینیِ کد می‌شود، بلکه باعث کاهش پیچیدگی و احتمال خطا نیز می‌شود. برای پیاده‌سازی SRP در سی‌پلاس‌پلاس مثالی خواهم زد؛ ابتدا باید کلاس را به شکلی طراحی کنید که فقط یک مسئولیت را در بر داشته باشد. به عنوان مثال، فرض کنید یک کلاس برای محاسبه‌ٔ مساحت یک شکل هندسی طراحی می‌کنید. با توجه به SRP، این کلاس فقط باید مسئول محاسبه‌ٔ مساحت باشد و هیچ وظیفه‌ای دیگر را نباید برعهده بگیرد. class Shape { public: virtual double area() const = 0; }; class Rectangle : public Shape { public: Rectangle(double h, double w) : height(h), width(w) {} double area() const override { return height * width; } private: double height; double width; }; class Circle : public Shape { public: Circle(double r) : radius(r) {} double area() const override { return 3.1415 * radius * radius; } private: double radius; }; در این مثال، کلاس Shape یک مسئولیت واحد دارد که محاسبه‌ٔ مساحت شکل هندسی است. همینطور کلاس‌های Rectangle و Circle نیز فقط مسئول محاسبه‌ٔ مساحت هر یک از شکل‌های هندسی خود هستند. به این ترتیب، هر یک از این کلاس‌ها فقط یک مسئولیت دارند و تغییراتی که در آینده رخ می‌دهد، مربوط به تابعی است که این مسئولیت را پوشش می‌دهد و هرگونه تغییرات دیگری نباید شامل کلاس شود. برای پیاده‌سازی OCP اصلِ Open/Closed Principle (اصل OCP) در شیء‌گرایی به معنی ایجاد کلاس‌ها به گونه‌ای است که برای اضافه کردن ویژگی جدید به یک برنامه، نیاز به تغییر کد قبلی نباشد. به عبارت دیگر، کلاس‌ها باید برای توسعه باز باشند (Open)، اما برای تغییر نباشند (Closed). برای پیاده‌سازی OCP، می‌توانید از ارث‌بری، پلی‌مورفیسم، استفاده از ابستراکت کلاس‌ها (کلاس‌های انتزاعی)، الگوی تزریق وابستگی و ... استفاده کنید. این اصل بهبود پذیری (extensibility) و بهره‌وری کد را بهبود می‌بخشد. همچنین برای پیاده‌سازی OCP، می‌توانید از الگوی Visitor و Strategy استفاده کنید. این باعث می‌شود که کلاس‌های شما قابلیت بسته‌بودن (Close) و در عین حال قابلیت گسترش ‌(Open) را داشته باشند. به عنوان مثال، فرض کنید یک برنامه داریم که می‌تواند اشکال هندسی مختلف را رسم کند. برای پیاده‌سازی OCP، می‌توانید کلاس اشکال هندسی را به گونه‌ای طراحی کنید که بتوانید به راحتی از آن‌ها ارث‌بری کنید و اشکال جدیدی را به سیستم اضافه کنید بدون ایجاد تغییرات بیشتر در کد قبلی. به عنوان مثال، اینجا یک کد ساده برای این کار نوشته شده است: #include <iostream> #include <vector> class Shape { public: virtual void draw() = 0; }; class Rectangle : public Shape { public: void draw() override { std::cout << "Drawing a rectangle\n"; } }; class Circle : public Shape { public: void draw() override { std::cout << "Drawing a circle\n"; } }; class GraphicEditor { public: void drawAllShapes(std::vector<Shape*> shapes) { for (auto shape : shapes) { shape->draw(); } } }; int main() { GraphicEditor editor; std::vector<Shape*> shapes = { new Rectangle(), new Circle() }; editor.drawAllShapes(shapes); for (auto shape : shapes) { delete shape; } return 0; } در این مثال، کلاس Shape در واقع یک واسط برای هر یک از شکل‌های هندسی است. کلاس Rectangle و کلاس Circle از کلاس Shape ارث‌بری کرده‌اند و تابع draw آن را پیاده‌سازی کرده‌اند. به این ترتیب، می‌توانید در آینده اشکال هندسی جدیدی را به کد اضافه کنید بدون نیاز به تغییر کد اصلی. برای پیاده‌سازی LSP اصل LSP به معنی اصل جایگزینی قابل توجه لیسکوف (Liskov Substitution Principle) در شیء‌گرایی به این مفهوم است که باید بتوان اشیاء موروثی از یک کلاس را با اشیاء کلاس والد جایگزین کرد. به عبارت دیگر، هر جایگزین یا زیرکلاس باید بتواند عملکرد و ویژگی‌های کلاس والد را حفظ کند و بدون هیچ تغییری، به جای کلاس والد استفاده شود. در واقع، هدف این اصل این است که به جای ایجاد جایگزین‌هایی که منجر به عملکرد غیرقابل پیش‌بینی می‌شوند، جایگزین‌هایی باشند که با انجام کارهایی مانند جایگزینی هنوز هم به نحو شایسته عمل کنند. فرض کنید که گربه و سگ، از یک کلاس حیوان وارثی هستند. برای همه‌ٔ حیوانات منطقی است که بتوانند صدای حیوان را تولید کنند. در اینجا با توجه به اصل LSP، باید بتوانیم به جای یک شیء گربه، یک شیء سگ یا شیء کلاس والدِ حیوان را به عنوان جایگزین استفاده کنیم و همچنین از آن‌ها بخواهیم که قابلیت تولید صدا را داشته باشند. به عبارت دیگر، صدای گربه و صدای سگ برای ما دقیقاً در یک رده‌بندی هستند و در همان حیطه معنایی قرار دارند، بنابراین باید بتوانیم هر یک از آن‌ها را به عنوان جایگزین برای دیگری استفاده کنیم. یک مثال ساده از اصل LSP در C++20، می‌تواند مربوط به کلاس‌های Shape و Rectangle باشد. فرض کنید کلاس Rectangle از کلاس Shape و از آن ارث‌بری کرده باشد. برای رعایت اصل LSP، کلاس Rectangle باید تمام روش‌های کلاس Shape را پیاده‌سازی کند، به گونه‌ای که در هر جایی که در کد از کلاس Shape استفاده می‌شود، می‌توانیم جایگزین آن را با کلاس Rectangle استفاده کنیم. کلاس Shape می‌تواند به صورت زیر باشد: class Shape { public: virtual double area() = 0; virtual double perimeter() = 0; }; و کلاس Rectangle از شکل یک مستطیل با طول و عرض دلخواه پیاده‌سازی شده است: class Rectangle : public Shape { private: double length; double width; public: Rectangle(double l, double w) : length(l), width(w) {} double area() override { return length * width; } double perimeter() override { return 2 * (length + width); } }; حال، با استفاده از این کلاس‌ها، می‌توانیم مستطیلی با طول و عرض دلخواه ایجاد کنیم و روش‌های کلاس Shape را روی آن صدا بزنیم: Shape* shapePtr = new Rectangle(4, 6); double area = shapePtr->area(); double perimeter = shapePtr->perimeter(); در اینجا، کلاس Rectangle با کلاس Shape جایگزین شده و اصل LSP رعایت شده است، به این معنی که هر جایی که از کلاس Shape استفاده شده، می‌توانیم جایگزین آن را با کلاس Rectangle استفاده کنیم، بدون هیچ تغییری در کد قبلی. برای پیاده‌سازی ISP اصل ISP به معنی اصل جداسازی رابط (Interface Segregation Principle) در شیء‌گرایی به این مفهوم است که باید رابط‌ها را به گونه‌ای طراحی کرد که اشیاء فقط به آنچه برایشان لازم است دسترسی داشته باشند و به سایر اجزای رابط دسترسی نداشته باشند. به عبارت دیگر، باید یک رابط یکتا و بزرگ به چندین رابط کوچک و مجزا تفکیک شود تا برای هر کلاس، فقط تعداد کم و لازمی از ویژگی‌ها و روش‌ها در دسترس باشد. برای پیاده‌سازی ISP، می‌توانید از الگوهای طراحی مانند واسط‌ها (Interfaces) و کلاس‌های واسط (Abstract Classes) استفاده کنید. با استفاده از این الگوها، می‌توانید پیچیدگی‌های شناور در برنامه خود را کاهش داده و تغییرات را در کد خود به راحتی انجام دهید. در واقع، هدف این اصل این است که کلاینت‌ها باید بتوانند با استفاده از رابط‌های ساده تر و متعارف، با سیستم تعامل داشته باشند. این روش منجر به افزایش قابلیت توسعه و خودکارسازی کد، بهره‌وری بالا و حتی صرفه‌جویی در زمان و هزینه خواهد شد. برای مثال نمونهٔ زیر به عنوان بخشی از پردازش تصویر می‌باشد: ابتدا واسط ImageTransformer را تعریف می‌کنیم که حاوی متدهای تبدیل تصویر به سیاه و سفید و برعکس آن است: class ImageTransformer { public: virtual void transformToBlackAndWhite() = 0; virtual void transformToColor() = 0; }; سپس دو کلاس ImageToBlackAndWhiteTransformer و ImageToColorTransformer را برای پیاده‌سازی واسط ImageTransformer تعریف می‌کنیم: class ImageToBlackAndWhiteTransformer: public ImageTransformer { public: void transformToBlackAndWhite() override { // Implement the transformation to black and white } }; class ImageToColorTransformer: public ImageTransformer { public: void transformToColor() override { // Implement the transformation to color } }; حال می‌توانیم از هر یک از کلاس‌های ImageToBlackAndWhiteTransformer و ImageToColorTransformer برای پردازش تصویر استفاده کنیم. در نهایت، به عنوان مثالی از استفاده از متد‌های رابط ImageTransformer، کد زیر را در نظر بگیرید: void processImage(ImageTransformer& transformer) { transformer.transformToBlackAndWhite(); transformer.transformToColor(); } در این کد، با گرفتن یک شیء از کلاسی که از واسط ImageTransformer ارث‌بری کرده است، می‌توانیم تصویر را به سیاه و سفید و برعکس آن تبدیل کنیم که بر اساس اصل ISP طراحی شده‌است. برای پیاده‌سازی اصل ISP در C++20 به‌طور کلی، می‌توان از این ویژگی بهره برد که به نام concepts شناخته می‌شود. این ویژگی به برنامه نویسان امکان می‌دهد که شرایط و محدودیت‌هایی را برای قالب‌ها، ورودی‌ها و خروجی‌ها تعریف کنند و باعث شود که کد بهتری با پایداری بیشتری نوشته شود. برای استفاده از این ویژگی در پیاده‌سازی اصل ISP در C++20، می‌توانید از مفهومی استفاده کنید که برای اطمینان از قابلیت اجرا و خطاهای برنامه سازی موجود است. برای مثال، در کد زیر، الگوهای واسط که برای پردازش تصویر استفاده می‌شوند، با نام‌های ImageTransformer و GrayscaleTransformer (با استفاده از template) تعریف شده‌اند. هر کدام از این الگوهای واسط، تعدادی عملیات مشخص شده را تعریف می کنند. سپس با استفاده از این الگوها، کلاس ImageProcessor (نیز با استفاده از template) برای پردازش تصویر طراحی شده است. template<typename T> concept ImageTransformer = requires(T t, cv::Mat image) { { t.transform_to_grayscale(image) } -> cv::Mat; { t.transform_to_rgb(image) } -> cv::Mat; }; template<typename T> concept GrayscaleTransformer = requires(T t, cv::Mat image) { { t.transform_to_grayscale(image) } -> cv::Mat; }; template <typename T> class ImageProcessor { public: ImageProcessor(T* transformerPtr) : transformerPtr_{ transformerPtr } { } cv::Mat transform_to_grayscale(cv::Mat image) { return transformerPtr_->transform_to_grayscale(image); } cv::Mat transform_to_rgb(cv::Mat image) { return transformerPtr_->transform_to_rgb(image); } private: T* transformerPtr_; }; همچنین، می‌توانید کلاس‌های مربوط به پردازش تصویر یعنی GrayscaleImageTransformer و RGBImageTransformer را به این الگوها منطبق کنید. در کد زیر، چک کردن اینکه یک کلاس منطبق بر پیشنیازهای ImageTransformer است یا نه، انجام شده است. class GrayscaleImageTransformer : public GrayscaleTransformer { public: cv::Mat transform_to_grayscale(cv::Mat image) override { cv::Mat grayscaleImage; cv::cvtColor(image, grayscaleImage, cv::COLOR_BGR2GRAY); return grayscaleImage; } }; class RGBImageTransformer : public ImageTransformer { public: cv::Mat transform_to_grayscale(cv::Mat image) override { cv::Mat grayscaleImage; cv::cvtColor(image, grayscaleImage, cv::COLOR_BGR2GRAY); return grayscaleImage; } cv::Mat transform_to_rgb(cv::Mat image) override { cv::Mat rgbImage; cv::cvtColor(image, rgbImage, cv::COLOR_GRAY2BGR); return rgbImage; } }; int main() { GrayscaleImageTransformer grayscaleTransformer; RGBImageTransformer rgbTransformer; ImageProcessor grayscaleProcessor{ &grayscaleTransformer }; cv::Mat image; image = cv::imread("image.jpg"); auto grayscaleResult = grayscaleProcessor.transform_to_grayscale(image); ImageProcessor rgbProcessor{ &rgbTransformer }; auto rgbResult = rgbProcessor.transform_to_rgb(grayscaleResult); cv::imwrite("grey.jpg", grayscaleResult); cv::imwrite("rgb.jpg", rgbResult); return 0; } برای پیاده‌سازی DIP DIP یا Dependency Inversion Principle (اصل وابستگی معکوس) یکی از اصول SOLID در شیء‌گرایی است که به مفهوم وابستگی به جایی یا Inversion of Control (IOC) هم معروف است. اصل DIP بیان می‌کند که برنامه باید به گونه‌ای طراحی شود که وابستگی به جزئیات پیاده‌سازی برنامه کاهش یابد و به جای آن، برنامه باید بر اساس واسط‌ها (interface) ارتباط برقرار کند، به گونه‌ای که خود وابستگی به جزئیات پیاده‌سازی به صورت بالادستی بر اساس واسط‌ها مدیریت شود. با استفاده از اصل DIP، کد قابلیت بازگشت و تغییر بهتر را دارد. این بدان معناست که تغییر در پیاده‌سازی یک کد، تنها روی کد فعلی تأثیر نمی‌گذارد و به خاطر استفاده از واسط‌ها، به صورت گسترده‌تر در برنامه تأثیر می‌گذارد. با رعایت اصل DIP، کدها با استفاده از واسط‌ها باید طراحی شوند و نباید به کد پیاده‌سازی جزئیات برچسب تمایل یا وابستگی داشته باشند. به عبارت دیگر، برنامه باید بر اساس قرارداد کار کند نه کد پیاده‌سازی. یک مثال ساده از پیاده‌سازی DIP در C++ به صورت زیر است: فرض کنید یک برنامه ساده را برای محاسبه جدول ضرب در نظر بگیرید. برای پیاده‌سازی این برنامه، یک کلاس MatrixCalculator وجود دارد که دارای دو متد است که برای محاسبه جدول ضرب به کار می‌روند: multiply و print. ابتدا یک واسط مشترک بین MatrixCalculator و کلاس‌های مختلف جدول تعریف می‌کنیم: class IMatrix { public: virtual void multiply() = 0; virtual void print() = 0; }; سپس دو کلاس Matrix2x2 و Matrix3x3 را برای پیاده‌سازی واسط IMatrix تعریف می‌کنیم: class Matrix2x2 : public IMatrix { public: void multiply() { // implementation for 2x2 matrix multiplication } void print() { // implementation for 2x2 matrix printing } }; class Matrix3x3 : public IMatrix { public: void multiply() { // implementation for 3x3 matrix multiplication } void print() { // implementation for 3x3 matrix printing } }; حالا کلاس MatrixCalculator را به گونه‌ای تغییر می‌دهیم که به جای استفاده از پیاده‌سازی خاص هر کلاس، از واسط IMatrix استفاده کند: class MatrixCalculator { private: IMatrix* matrix; public: MatrixCalculator(IMatrix* m) : matrix(m) {} void multiply() { matrix->multiply(); } void print() { matrix->print(); } }; بنابراین حالا می‌توانیم کلاس MatrixCalculator را به صورت زیر استفاده کنیم: IMatrix* m2x2 = new Matrix2x2(); MatrixCalculator calculator2x2(m2x2); calculator2x2.multiply(); calculator2x2.print(); IMatrix* m3x3 = new Matrix3x3(); MatrixCalculator calculator3x3(m3x3); calculator3x3.multiply(); calculator3x3.print(); با این رویکرد، هر زمان که یک کلاس جدید با پیاده‌سازی واسط IMatrix ایجاد شود، می‌توانیم آن را به کلاس MatrixCalculator اضافه کرده و آن را بدون تغییر در کد MatrixCalculator استفاده کنیم. همچنین وابستگی MatrixCalculator به کلاس‌های Matrix2x2 و Matrix3x3 برای انجام کارش کاهش یافته است. در C++20 می‌توان از ویژگی concepts برای پیاده‌سازی DIP استفاده کرد. در اینجا مثال ساده‌ای از پیاده‌سازی DIP با ویژگی concepts در C++20 آورده شده است: #include <iostream> #include <concepts> template <typename T> concept Comparable = requires(T a, T b) { { a == b } -> std::convertible_to<bool>; { a != b } -> std::convertible_to<bool>; }; template <typename T> class Calculator { public: Calculator(T num1, T num2) : num1_(num1), num2_(num2) {} T add() requires Comparable<T> { return num1_ + num2_; } private: T num1_; T num2_; }; int main() { Calculator<int> intCalc(5, 10); std::cout << intCalc.add() << std::endl; Calculator<float> floatCalc(5.5, 10.5); std::cout << floatCalc.add() << std::endl; // Calculator<std::string> strCalc("hello", "world"); // Compile-time error return 0; } در این مثال، ما از ویژگی concepts برای تعریف واسط Comparable استفاده کرده‌ایم. همچنین، کلاس Calculator از واسط Comparable به عنوان یک شرط برای تعریف تابع add استفاده شده است. با این رویکرد، ما به سادگی می‌توانیم به جای وابستگی به یک نوع دقیق، وابستگی به یک واسط را ایجاد کنیم.
  12. کامبیز اسدزاده

    علیکم سلام، طبق این دو آموزش پیش برید. پیکربندی فریم‌ورک کیوت برای پلتفرم اندروید پیکربندی و به‌روز‌ رسانی کیوت ۶.۴ برای اندروید ۱۳
  13. کامبیز اسدزاده

    ترکیب کد‌های ++C با ورد‌پرس بدون شکستن کد آن

    ساده‌ترین راه برای افزودن کد سفارشی به سایت‌هایی که بر پایهٔ وردپرس ساخته شده‌اند، بدون شکستن کد آن چیست؟ زبان برنامه‌نویسیِ ++C یکی از محبوب‌ترین زبان‌های برنامه‌نویسی است. آخرین آمار نشان می‌دهد که این زبان با سرعت بسیار زیادی در حال توسعه و پوست‌اندازی است. این زبان، علیرغم اینکه بیش از 40 سال از عمرش می‌گذرد، همچنان زبان انتخابی برای بسیاری از برنامه‌نویسان در سراسر جهان است. برای بسیاری از موارد مانند برنامه‌های کاربردی دستکاری تصویر، بازی‌های سه بعدی، شبیه سازی‌ها، مرورگرهای وب و نرم‌افزارهای سازمانی استفاده می‌شود. دلیلش این است که سی‌پلاس‌پلاس در حال تکامل است، به انرژی سبز اهمیت می‌دهد و در عین حال کارآیی بسیار بالا و بهینه‌ای دارد. از آنجایی که این زبان پیچیده‌تر از سایر زبان‌های برنامه‌نویسی است، یک کمیتهٔ فرعی از یک سازمان چند سطحی وظیفه استانداردسازی آن را بر عهده دارد. سی‌پلاس‌پلاس اکنون از یک مدل قطار پیروی می‌کند و هر سه سال یکبار نسخه‌های جدید دریافت می‌کند که در مورد استاندارد‌های جدید، اخیراً مقالاتی منتشر شده است. سی‌پلاس‌پلاس معمولاً برای توسعهٔ نرم‌افزار در مقیاس بزرگ استفاده می‌شود، اما می‌توان از آن برای پروژه‌های توسعه وب نیز استفاده کرد. ممکن است تعجب کنید که چگونه از آن با وردپرس، یکی از محبوب‌ترین سیستم‌های مدیریت محتوا و سازندگان وب سایت امروزه استفاده کنید. در این باره قبلاً من مقالاتی را منتشر کرده‌ام که به صورت زیر آمده‌اند: در حالی که بسیاری از وب سایت‌ها با استفاده از وردپرس به عنوان پایه ساخته می‌شوند، این لزوماً به این معنی نیست که اکوسیستم وردپرس تکامل یافته یا کامل است. به عنوان مثال، وردپرس تمرکز زیادی بر تجربه‌کاربران و نیازهای وبلاگ نویسان دارد، به همین دلیل است که بر چهار زبان HTML، CSS، جاوا اسکریپت و PHP متکی است و این بدان معناست که برای توسعه‌دهندگانی که می‌خواهند به طور کامل از قدرت آن استفاده کنند، محدودیت‌هایی وجود دارد. در حالی که افزونه‌هایی مانند Custom Post Types برای گسترش عملکرد وردپرس وجود دارد و راه‌های زیادی برای افزودن قابلیت‌های جدید بدون شروع از ابتدا وجود ندارد. همچنین، افزودن کد ++C به طور مستقیم به یک سایت وردپرس توصیه نمی‌شود زیرا به طور بالقوه می‌تواند آسیب پذیری‌های امنیتی را ایجاد کند و وب سایت را خراب کند. با این حال، اگر نیاز خاصی به اجرای کد ++C در سایت وردپرس شما وجود دارد، در اینجا روش‌هایی که می‌توانید آن را انجام دهید گفته شده‌است: شما می توانید یک برنامه یا کتابخانه مستقل ++C ایجاد کنید و سپس آن را از طریق وب API در معرض دید قرار دهید، که می‌تواند توسط وردپرس مصرف شود. بیایید نگاهی به مراحل کلی بیندازیم: کد ++C خود را بنویسید و آن را در یک برنامه یا کتابخانه مستقل کامپایل کنید. عملکرد برنامه یا کتابخانه ++C را از طریق وب API به نمایش بگذارید. شما می‌توانید از یک کتابخانه به عنوان cpprestsdk برای ایجاد نقاط پایانی API استفاده کنید. برنامه یا کتابخانه ++C را بر روی یک سرور، یا در همان سرور سایت وردپرس خود یا در یک سرور جداگانه، مستقر کنید. در سایت وردپرس خود، از یک افزونه یا کد سفارشی برای درخواست HTTP به API و بازیابی نتایج استفاده کنید. شما می‌توانید از کتابخانه‌ای مانند cURL برای ارائه چنین درخواست‌هایی استفاده کنید. در صورت نیاز از نتایج بازیابی شده در سایت وردپرس خود استفاده کنید. راه دیگر برای افزودن قابلیت ++C به سایت وردپرس استفاده از افزونه‌ای است که به شما امکان می‌دهد کد ++C را مستقیماً در صفحات یا پست‌های وردپرس جاسازی کنید. مراحل بسته به افزونه‌ای که استفاده می‌کنید متفاوت است، اما در اینجا چند مرحله کلی وجود دارد که می‌تواند کمک کند. افزونه‌ای را که از کد ++C پشتیبانی می‌کند را در سایت وردپرس خود نصب کنید. یک صفحه یا پست جدید در وردپرس ایجاد کنید و کد کوتاه [cpp] را به قسمت محتوا اضافه کنید. در کد از نوع برچسب‌ِ [cpp]، کد ++C خود را اضافه کنید. صفحه یا پست را منتشر کنید و آن را مشاهده کنید تا کد جاسازی شده ++C را در عمل ببینید. مجدداً توجه داشته باشید که افزودن کد ++C به طور مستقیم به یک صفحه یا پست می‌تواند خطرناک باشد. مهم است که پیاده‌سازی خود را به طور کامل آزمایش کنید تا مطمئن شوید که ایمن و قابل اعتماد است. از هر روشی که استفاده می‌کنید، به یک پایه محکم در سی‌پلاس‌پلاس و مهارت‌های یکپارچه سازی وردپرس نیاز دارد. وقتی صحبت از وردپرس به میان می‌آید، شاید بهتر باشد از زبانی مانند PHP استفاده کنید. اگر می‌خواهید دربارهٔ ++C و نحوهٔ به حداکثر رساندن آن برای پروژه‌تان بیشتر بدانید، می‌توانید به آموزه‌های مربوط به سی‌پلاس‌پلاس در این سایت را بررسی کنید یا کتاب‌های پیشنهادی در بخش معرفی زبان را بخوانید. فراموش نکنید که سی‌پلاس‌پلاس یک زبان جذاب و همیشه در حال تکامل است و افزودن آن به مجموعه مهارت‌های شما سودمند است.
  14. کامبیز اسدزاده

    نهایی‌سازی استاندارد ۲۳ (استاندارد ۲۶ در راه است)

    با سلام و درود، پیرو مقالهٔ قبلی در رابطه با بخشی از نهایی‌سازی‌های استاندارد ۲۳ در این مقاله قصد داریم در رابطه با استاندارد ۲۶ و نهایی‌سازی‌های ۲۳ یک جمع‌بندی داشته باشیم که بسیار در شناخت و به‌روز رسانی سریع از پیشرفت این زبان را به ما نشان می‌دهد. طبق جلسات اخیر از کمیتهٔ استاندارد‌سازی، در اولین جلسه، کمیته بر اصلاح ویژگی‌های 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 دارید، با خیال راحت آنها را به اشتراک بگذارید. یا - حتی بهتر - ارسال یک پیشنهاد را در نظر بگیرید.
  15. با سلام، با توجه به گزارش آنتونی پولوخین که یکی از اعضای کمیتهٔ استاندارد‌سازی 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 بود، اگرچه در آخرین جلسه ویژگی‌های مورد انتظار بسیاری اضافه شد. نوآوری‌هایی برای توسعه‌دهندگان تعبیه شده، شیمیدانان/فیزیکدانان/ریاضیدانان/...، توسعه‌دهندگان کتابخانه‌های یادگیری ماشین، و حتی توسعه‌دهندگانی که روی برنامه‌های کاربردی با بار بالا کار می‌کنند، وجود دارد.
×
×
  • جدید...