برای ساخت یک شیء std::optional،
روشهای متنوعی در اختیار برنامهنویس قرار گرفته است که هرکدام برای
سناریوی خاصی طراحی شدهاند. سازندهی پیشفرض، یک شیء خالی (فاقد مقدار)
ایجاد میکند که با std::nullopt نیز قابل دستیابی است. همچنین امکان کپیسازی یا انتقال (move) از یک optional دیگر وجود دارد که رفتار آن به نوع مقداردهی اولیه بستگی دارد. مهمترین سازندهها، آنهایی هستند که از std::in_place استفاده میکنند و امکان ساخت مستقیم مقدار درون optional
را بدون کپی یا انتقال اضافی فراهم میسازند. این روش برای انواعی که
کپیبرداری از آنها پرهزینه است یا سازندهی غیرپیشفرض دارند، بسیار
کارآمد محسوب میشود.
قواعد و محدودیتهای نوع T در std::optional
استفاده از std::optional با هر نوع دادهای مجاز نیست و قواعد مشخصی برای نوع T تعریف شده است. نوع T باید از نوع تخریبپذیر (Destructible) باشد و انواع مرجع، توابع، آرایهها و void در آن مجاز نیستند. همچنین استفاده از std::nullopt_t و std::in_place_t بهعنوان نوع T غیرمجاز است. این محدودیتها بهدلیل طراحی optional بهعنوان یک ظرف (Container) برای یک مقدار واحد است که باید چرخهی حیات آن را بهدرستی مدیریت کند.
روشهای دسترسی به مقدار ذخیرهشده
std::optional سه روش اصلی برای دسترسی به مقدار ذخیرهشده ارائه میدهد که هرکدام سطح متفاوتی از ایمنی و سربار را به همراه دارند. عملگرهای * و -> دسترسی مستقیم و بدون بررسی را فراهم میکنند و در صورت خالی بودن optional، رفتار تعریفنشده (Undefined Behavior) رخ میدهد. در مقابل، متد value() با انجام بررسی، در صورت خالی بودن optional، استثنای std::bad_optional_access پرتاب میکند. متد value_or نیز یک مقدار پیشفرض دریافت کرده و در صورت خالی بودن optional، آن مقدار را بازمیگرداند و از پرتاب استثنا جلوگیری میکند.
متدهای تغییر مقدار: reset، swap و emplace
برای تغییر محتوای یک optional، سه متد اصلی در دسترس است. متد reset، مقدار موجود (در صورت وجود) را نابود کرده و optional را به حالت خالی بازمیگرداند. متد swap محتوای دو optional
را با یکدیگر مبادله میکند و در سناریوهای مختلف، رفتار متفاوتی از خود
نشان میدهد: اگر هر دو خالی باشند، کاری انجام نمیشود؛ اگر یکی مقدار
داشته باشد، مقدار بهصورت انتقالی به دیگری منتقل میشود؛ و اگر هر دو
مقدار داشته باشند، مقدارهای درون آنها با یکدیگر تعویض میشوند. متد emplace نیز مقدار جدیدی را مستقیماً درون optional میسازد و مقدار قبلی (در صورت وجود) را نابود میکند.
توابع کمکی: std::make_optional
تابع std::make_optional یک روش جایگزین و گاهی سادهتر برای ساخت اشیاء std::optional ارائه میدهد. این تابع در سه حالت مختلف قابل استفاده است: با دریافت یک مقدار و ساخت optional از روی آن، با دریافت آرگومانهای سازنده و ساخت مستقیم مقدار درون optional، و با دریافت یک initializer_list همراه با آرگومانهای اضافی. یکی از مزایای مهم این تابع، استفاده از تضمین کپیبرداری (Guaranteed Copy Elision) است که در برخی موارد نیاز به حرکتدهی (move) را حذف میکند.
عملیاتهای مقایسهای
std::optional از مجموعهی کاملی از عملگرهای مقایسهای پشتیبانی میکند. دو شیء optional را میتوان با یکدیگر مقایسه کرد و همچنین میتوان یک optional را با std::nullopt یا با یک مقدار از نوع T مقایسه نمود. قواعد مقایسه بهگونهای طراحی شدهاند که رفتار طبیعی و قابلپیشبینی داشته باشند.
قابلیتهای جدید در C++23
استاندارد C++23 قابلیتهای جدیدی را به std::optional افزوده است که الهامگرفته از برنامهنویسی تابعی هستند. این قابلیتها شامل متدهای مونادیک (Monadic Operations) مانند transform، and_then و or_else میشوند. متد transform یک تابع را روی مقدار موجود اعمال کرده و نتیجه را در یک optional جدید برمیگرداند. متد and_then مشابه transform است، با این تفاوت که تابع ورودی خود باید یک optional بازگرداند و از زنجیرهسازی چندین عملیات که ممکن است شکست بخورند پشتیبانی میکند. متد or_else نیز در صورت خالی بودن optional، یک تابع را فراخوانی میکند و برای مدیریت موارد خطا کاربرد دارد.
کلیدواژه ها : std::optional methods-متدهای std::optional-C++17 optional guide-سازندههای optional-std::optional rules-std::optional value-std::optional value_or-std::optional emplace-std::optional swap-std::optional reset-std::make_optional-std::optional comparisons-std::optional C++23-std::optional transform-std::optional and_then-std::optional or_else-monadic operations optional-قواعد std::optional-آموزش std::optional-مدیریت مقدار تهیپذیر-std::optional in place construction