یکی از الگوریتمهای جدید و بسیار پرکاربردی که در 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