std::ranges::clamp
| (C++23) <algorithm>
|
||
| 헤더 |
||
template< class T, class Proj = std::identity,
std::indirect_strict_weak_order<std::projected<const T*, Proj>> Comp =
ranges::less >
constexpr const T&
clamp( const T& v, const T& lo, const T& hi, Comp comp = {}, Proj proj = {} );
|
에 정의됨 | |
(C++20부터)v의 값이 [lo, hi] 범위 내에 있으면 v을 반환하고, 그렇지 않으면 가장 가까운 경계값을 반환합니다.
lo이 hi보다 크면 동작이 정의되지 않습니다.
이 페이지에 설명된 함수형 개체는 알고리즘 함수 객체 (비공식적으로 niebloid라고 함)입니다. 즉:
- 이들 중 하나를 호출할 때 명시적 템플릿 인자 목록을 지정할 수 없습니다.
- 이들 중 어느 것도 인자 종속 조회에 보이지 않습니다.
- 이들 중 하나가 일반적인 비정규화 조회에서 함수 호출 연산자 왼쪽의 이름으로 발견되면 인자 종속 조회가 금지됩니다.
매개변수
| v | - | 제한할 값 |
| lo, hi | - | v 를 제한할 경계값 |
| comp | - | 투영된 요소들에 적용할 비교 연산 |
| proj | - | v , lo 및 hi 에 적용할 투영 연산 |
반환값
lo 의 투영 값이 v 의 투영 값보다 작으면 lo 에 대한 참조, hi 의 투영 값이 v 의 투영 값보다 작으면 hi 에 대한 참조, 그렇지 않으면 v 에 대한 참조.
복잡도
최대 두 번의 비교와 세 번의 투영 적용.
가능한 구현
struct clamp_fn { template<class T, class Proj = std::identity, std::indirect_strict_weak_order<std::projected<const T*, Proj>> Comp = std::ranges::less> constexpr const T& operator()(const T& v, const T& lo, const T& hi, Comp comp = {}, Proj proj = {}) const { auto&& pv = std::invoke(proj, v); if (std::invoke(comp, std::forward<decltype(pv)>(pv), std::invoke(proj, lo))) return lo; if (std::invoke(comp, std::invoke(proj, hi), std::forward<decltype(pv)>(pv))) return hi; return v; } }; inline constexpr clamp_fn clamp; |
참고 사항
std::ranges::clamp
by reference produces a dangling reference if one of the parameters is a temporary and that parameter is returned:
int n = -1; const int& r = std::ranges::clamp(n, 0, 255); // r은 댕글링 참조입니다
만약 v 가 어느 한 경계와 동등하게 비교되면, 경계가 아닌 v 에 대한 참조를 반환합니다.
프로젝션이 값을 반환하고 비교자가 값을 인수로 받는 경우, 프로젝션 결과 타입에서 비교자 매개변수 타입으로의 이동(move)이 복사(copy)와 동등하지 않다면 이 함수를 사용해서는 안 됩니다.
std::invoke
를 통한 비교가 프로젝션의 결과를 변경할 경우,
std::regular_invocable
의 의미론적 요구사항(이는
std::indirect_strict_weak_order
에 포함됨)으로 인해 동작이 정의되지 않습니다.
표준은 투영(projection) 결과의 값 범주(value category)가 보존되어야 하며, proj 는 v 에 대해 한 번만 호출될 수 있습니다. 이는 prvalue인 투영 결과가 비교자(comparator)에 대한 두 번의 호출을 위해 캐시되고 두 번 이동되어야 함을 의미합니다.
- libstdc++ 는 이를 준수하지 않으며 항상 projection 결과를 lvalue로 전달합니다.
- libc++ 는 projection을 두 번 실행했으나, Clang 18에서 수정되었습니다.
- MSVC STL 는 projection을 두 번 실행했으나, VS 2022 17.2에서 수정되었습니다.
예제
#include <algorithm> #include <cstdint> #include <iomanip> #include <iostream> #include <string> using namespace std::literals; namespace ranges = std::ranges; int main() { std::cout << "[raw] [" << INT8_MIN << ',' << INT8_MAX << "] " "[0" << ',' << UINT8_MAX << "]\n"; for (int const v : {-129, -128, -1, 0, 42, 127, 128, 255, 256}) std::cout << std::setw(4) << v << std::setw(11) << ranges::clamp(v, INT8_MIN, INT8_MAX) << std::setw(8) << ranges::clamp(v, 0, UINT8_MAX) << '\n'; std::cout << std::string(23, '-') << '\n'; // 투영 함수 const auto stoi = [](std::string s) { return std::stoi(s); }; // 위와 동일하지만 문자열 사용 for (std::string const v : {"-129", "-128", "-1", "0", "42", "127", "128", "255", "256"}) std::cout << std::setw(4) << v << std::setw(11) << ranges::clamp(v, "-128"s, "127"s, {}, stoi) << std::setw(8) << ranges::clamp(v, "0"s, "255"s, {}, stoi) << '\n'; }
출력:
[raw] [-128,127] [0,255] -129 -128 0 -128 -128 0 -1 -1 0 0 0 0 42 42 42 127 127 127 128 127 128 255 127 255 256 127 255 ----------------------- -129 -128 0 -128 -128 0 -1 -1 0 0 0 0 42 42 42 127 127 127 128 127 128 255 127 255 256 127 255
참고 항목
|
(C++20)
|
주어진 값들 중 더 작은 값을 반환합니다
(알고리즘 함수 객체) |
|
(C++20)
|
주어진 값들 중 더 큰 값을 반환합니다
(알고리즘 함수 객체) |
|
(C++20)
|
정수 값이 주어진 정수 타입의 범위 내에 있는지 확인합니다
(함수 템플릿) |
|
(C++17)
|
값을 한 쌍의 경계값 사이로 고정합니다
(함수 템플릿) |