یکی از الگوریتم‌های جدید و بسیار پرکاربردی که در C++17 به کتابخانه‌ی استاندارد اضافه شد، تابع std::clamp است که در هدر <algorithm> تعریف شده است . این تابع یک مقدار عددی یا اسکالر را در یک بازه‌ی مشخص، محدود (مقید) می‌کند؛ به‌گونه‌ای که اگر مقدار ورودی از کرانه‌ی پایین (lo) کوچک‌تر باشد، کرانه‌ی پایین بازگردانده می‌شود و اگر از کرانه‌ی بالا (hi) بزرگ‌تر باشد، کرانه‌ی بالا برگردانده می‌شود . اگر مقدار ورودی درون بازه قرار داشته باشد، خود مقدار بازگردانده می‌شود. این تابع، جایگزین کدهای تکراری و شرطی دست‌نویسی شده‌ای می‌شود که برنامه‌نویسان پیش از این برای محدودسازی مقادیر استفاده می‌کردند و هم خوانایی کد را افزایش می‌دهد و هم احتمال بروز خطا را کاهش می‌دهد .

نحوه‌ی عملکرد و امضای تابع

std::clamp در دو نسخه ارائه شده است. نسخه‌ی اول، از عملگر operator< برای مقایسه‌ی مقادیر استفاده می‌کند و نسخه‌ی دوم، یک شیء تابع مقایسه‌کننده (مانند std::less یا یک lambda) را به‌عنوان آرگومان چهارم دریافت می‌کند تا نحوه‌ی مقایسه را مشخص نماید . هر دو نسخه، ثابت‌بودن در زمان کامپایل (constexpr) را پشتیبانی می‌کنند. پارامترهای lo و hi باید به‌گونه‌ای باشند که lo از hi بزرگ‌تر نباشد؛ در غیر این صورت، رفتار برنامه تعریف‌نشده خواهد بود . تابع، پیچیدگی زمانی بسیار کمی دارد و نهایتاً از دو مقایسه برای تشخیص وضعیت مقدار ورودی استفاده می‌کند .

هشدار مهم در مورد بازگشت مرجع

مهم‌ترین نکته‌ای که در استفاده از std::clamp باید به آن توجه کرد، ماهیت بازگشت مرجع (Reference Return) آن است. این تابع، مقدار را به‌عنوان یک مرجع ثابت (const T&) بازمی‌گرداند. اگر یکی از آرگومان‌های ورودی (به‌ویژه کرانه‌ها) یک شیء موقت (Temporary) باشد و آن آرگومان به‌عنوان نتیجه بازگردانده شود، این مرجع به یک مرجع آویزان (Dangling Reference) تبدیل می‌شود . در عمل، این خطر زمانی رخ می‌دهد که از std::clamp با اعداد ثابت (literals) به‌عنوان کرانه استفاده می‌شود و نتیجه به یک مرجع انتساب داده می‌شود؛ زیرا اعداد ثابت، اشیاء موقتی محسوب می‌شوند. برای جلوگیری از این مشکل، بهتر است نتیجه را به‌صورت مقدار (Value) ذخیره کنید، نه مرجع .

مزایا و کاربردهای عملی

کاربرد اصلی std::clamp در سناریوهایی است که نیاز به محدودسازی مقادیر، مانند اعتبارسنجی ورودی‌ها، تنظیم سطح حجم صدا، محدودسازی رنگ‌های تصویر (RGB) بین ۰ تا ۲۵۵، یا در الگوریتم‌های پردازش سیگنال وجود دارد . بر اساس مستندات، می‌توان از این تابع برای محدودسازی یک‌باره‌ی کل عناصر یک کانتینر، با استفاده از std::transform نیز بهره برد . با این حال، نکته‌ی جالب‌توجهی که در گزارش‌های باگ کتابخانه‌های استاندارد دیده می‌شود، این است که پیاده‌سازی فعلی std::clamp برای نوع‌های پایه‌ای مانند float، کد اسمبلی کاملاً بهینه‌ای تولید نمی‌کند و ممکن است یک پیاده‌سازی دستی ساده با استفاده از max و min، کد سریع‌تری تولید کند . با وجود این نکته، std::clamp همچنان به‌دلیل وضوح و بیانگری بالا، یک انتخاب عالی برای کدنویسی مدرن C++ محسوب می‌شود.

کلیدواژه ها : std::clamp-محدودسازی مقدار در C++-C++17 clamp-مزایای std::clamp-الگوریتم‌های کاربردی C++17-نکات std::clamp-مقایسه clamp و کد دستی-کاربرد std::clamp-آموزش std::clamp-محدودسازی مقادیر عددی-تابع clamp در C++-پرفورمنس std::clamp-بهبود خوانایی کد-هدر algorithm در C++17