در برنامه‌نویسی، اغلب با موقعیت‌هایی مواجه می‌شویم که یک تابع یا عملیات ممکن است نتواند نتیجه‌ی معتبری تولید کند. پیش از C++17، راه‌حل‌های مختلفی برای این مسئله وجود داشت که هرکدام معایب خاص خود را داشتند. برخی از برنامه‌نویسان از مقادیر خاص مانند -1 برای نشان‌دادن خطا استفاده می‌کردند که این روش به‌شدت مستعد خطا و تفسیرهای اشتباه بود. برخی دیگر از اشاره‌گرها و nullptr بهره می‌بردند که سربار مدیریت حافظه و پیچیدگی‌های خاص خود را داشت. روش دیگر، استفاده از std::pair<T, bool> بود که اگرچه کار می‌کرد، اما خوانایی پایینی داشت و قصد برنامه‌نویس را به‌خوبی منتقل نمی‌کرد .

std::optional: راه‌حل استاندارد و نوع‌ایمن

C++17 با معرفی std::optional<T> در هدر <optional>، پاسخ استاندارد و زیبایی به این نیاز ارائه داد. یک شیء از نوع std::optional یا یک مقدار از نوع T را در خود دارد، یا اینکه خالی است و هیچ مقداری را ذخیره نکرده است . این نوع داده، به‌عنوان یک تایپ واژگانی (Vocabulary Type) طراحی شده تا در رابط‌های بین بخش‌های مختلف کد، منظور برنامه‌نویس را به‌روشنی بیان کند.

مزایای کلیدی

عدم تخصیص حافظه‌ی پویا: برخلاف برخی راه‌حل‌های دیگر، std::optional مقدار خود را مستقیماً درون خود ذخیره می‌کند و هیچ‌گاه حافظه‌ی پویا (Dynamic Memory) تخصیص نمی‌دهد . این ویژگی، آن را برای سیستم‌های با کارایی بالا بسیار مناسب می‌سازد.

وضوح و بیانگری: استفاده از std::optional در امضای توابع، قصد طراح را به‌خوبی منتقل می‌کند. تابع std::optional<T> f() به‌وضوح نشان می‌دهد که ممکن است نتیجه‌ای وجود نداشته باشد .

ایمنی نوع: برخلاف استفاده از مقادیر خاص، کامپایلر به شما کمک می‌کند تا همیشه وضعیت وجود یا عدم وجود مقدار را بررسی کنید.

نحوه‌ی کار با std::optional

ساخت یک std::optional به روش‌های مختلفی امکان‌پذیر است. می‌توان آن را به‌صورت پیش‌فرض ساخت که در حالت خالی قرار می‌گیرد، با یک مقدار از نوع T مقداردهی کرد، یا با استفاده از ثابت std::nullopt آن را به‌وضوح خالی درنظر گرفت.

برای بررسی وجود مقدار، از متد has_value() یا تبدیل ضمنی به bool استفاده می‌شود. دسترسی به مقدار نیز از طریق عملگر * یا متد value() انجام می‌گیرد . تفاوت اصلی این دو در رفتار هنگام خطاست: value() در صورت خالی بودن، استثنای std::bad_optional_access پرتاب می‌کند، درحالی‌که عملگر * چنین تضمینی ندارد . همچنین متد value_or راهی امن برای دسترسی به مقدار با ارائه‌ی یک مقدار پیش‌فرض در صورت خالی بودن فراهم می‌کند .

کاربردهای اصلی

بازگشت توابعی که ممکن است شکست بخورند: رایج‌ترین کاربرد std::optional، بازگشت نتیجه‌ی توابعی مانند جست‌وجو در یک پایگاه‌داده یا تبدیل رشته به عدد است که ممکن است موفقیت‌آمیز نباشند .

پارامترهای اختیاری توابع: به‌جای استفاده از اشاره‌گرها یا مقادیر پیش‌فرض خاص، می‌توان از std::optional برای پارامترهایی استفاده کرد که ممکن است مقدار نداشته باشند.

شروع‌دهی معوق (Delayed Initialization): در کلاس‌هایی که عضوی ممکن است در زمان ساخت شیء قابل مقداردهی نباشد، اما بعداً باید تعیین شود، std::optional ابزار مناسبی است

کلیدواژه ها : std::optional-مقدار تهی‌پذیر در C++-C++17 optional-مزایای std::optional-آموزش std::optional-std::nullopt-std::optional value-std::optional value_or-std::bad_optional_access-مدیریت مقدار در ++C-تایپ‌های واژگانی ++C-بررسی وجود مقدار در optional-شروع‌دهی معوق با optional-بازگشت خطا در ++C