utility_functional
utility_functional (함수 객체)
함수 객체는 함수 호출 연산자(function call operator)가 정의된 모든 객체를 의미해요. C++은 다양한 내장 함수 객체를 제공할 뿐만 아니라, 새로운 함수 객체를 생성하고 조작할 수 있는 기능도 함께 지원해요.
출처: cppreference
본문
함수 객체란?
함수 객체는 operator()를 정의한 객체예요. 일반 함수처럼 호출할 수 있으면서도, 객체이기 때문에 상태를 가질 수 있고 템플릿 인자로 전달하기도 쉬워요. C++ 표준 라이브러리의 많은 알고리즘과 어댑터가 함수 객체를 사용해요.
함수 호출 (Function invocation)
설명 전용 연산인 INVOKE(f, arg_0, arg_1, arg_2, ..., arg_N)은 다음과 같이 정의돼요. Obj는 arg_0의 비한정 타입, 즉 std::remove_cv<std::remove_reference<decltype(arg_0)>::type>::type이고, obj는 Obj 타입의 객체예요.
f가 클래스C의 멤버 함수 포인터라면:std::is_same<C, Obj>::value || std::is_base_of<C, Obj>::value가true이면(obj.*f)(arg_1, arg_2, ..., arg_N)로 호출해요.Obj가std::reference_wrapper의 특수화라면(obj.get().*f)(arg_1, arg_2, ..., arg_N)로 호출해요.- 그 외에는
((*obj).*f)(arg_1, arg_2, ..., arg_N)로 역참조한 객체에서 호출해요.
- 그렇지 않고
N == 0이고f가 클래스C의 데이터 멤버 포인터라면:std::is_same<C, Obj>::value || std::is_base_of<C, Obj>::value가true이면obj.*mptr로 접근해요.Obj가std::reference_wrapper의 특수화라면obj.get().*mptr로 접근해요.- 그 외에는
(*obj).*mptr로 역참조한 객체에서 접근해요.
- 그 외에는
f(arg_0, arg_1, arg_2, ..., arg_N)처럼 일반 호출 가능 객체로 호출해요.
설명 전용 연산 INVOKE<R>(f, arg_0, arg_1, arg_2, ..., arg_N)은 다음과 같이 정의돼요.
R이 (cv 한정된)void라면static_cast<void>(INVOKE(f, arg_0, arg_1, arg_2, ..., arg_N))로 처리해요.- 그 외에는
INVOKE(f, arg_0, arg_1, arg_2, ..., arg_N)의 결과를R로 암묵적으로 변환해요. Actual을decltype(INVOKE(f, arg_0, arg_1, arg_2, ..., arg_N))라고 할 때,std::reference_converts_from_temporary_v<R, Actual>이true라면INVOKE<R>(f, arg_0, arg_1, arg_2, ..., arg_N)은 ill-formed예요. (C++23부터)
std::invoke와 std::invoke_r(C++23부터)은 INVOKE 및 INVOKE<R>의 규칙에 따라 주어진 인자로 임의의 Callable 객체를 호출해요.
| 구성 요소 | 설명 |
|---|---|
invoke (C++17) |
주어진 인자로 임의의 Callable 객체를 호출해요. (함수 템플릿) |
invoke_r (C++23) |
반환 타입을 지정할 수 있으면서 주어진 인자로 임의의 Callable 객체를 호출해요. (함수 템플릿) |
함수 래퍼 (Function wrappers)
이 다형성 래퍼 클래스들은 임의의 함수 객체를 저장할 수 있게 지원해요.
| 구성 요소 | 설명 |
|---|---|
function (C++11) |
복사 생성 가능한 모든 호출 가능 객체의 복사 가능한 래퍼예요. (클래스 템플릿) |
move_only_function (C++23) |
주어진 호출 시그니처에서 한정사를 지원하는 모든 호출 가능 객체의 이동 전용 래퍼예요. (클래스 템플릿) |
copyable_function (C++26) |
주어진 호출 시그니처에서 한정사를 지원하는 복사 생성 가능한 모든 호출 가능 객체의 복사 가능한 래퍼예요. (클래스 템플릿) |
function_ref (C++26) |
임의의 호출 가능 객체를 소유하지 않는 래퍼예요. (클래스 템플릿) |
bad_function_call (C++11) |
빈 std::function을 호출할 때 던져지는 예외예요. (클래스) |
mem_fn (C++11) |
멤버 포인터로부터 함수 객체를 만들어요. (함수 템플릿) |
Identity
std::identity는 항등 함수 객체로, 인자를 변경하지 않고 그대로 반환해요.
| 구성 요소 | 설명 |
|---|---|
identity (C++20) |
인자를 변경하지 않고 그대로 반환하는 함수 객체예요. (클래스) |
부분 함수 적용 (Partial function application)
std::bind_front와 std::bind는 부분 함수 적용, 즉 함수에 인자를 결합하여 새로운 함수를 만드는 기능을 지원해요.
| 구성 요소 | 설명 |
|---|---|
bind_front (C++20) |
함수 객체에 여러 인자를 순서대로 앞에서부터 결합해요. (함수 템플릿) |
bind_back (C++23) |
함수 객체에 여러 인자를 순서대로 뒤에서부터 결합해요. (함수 템플릿) |
bind (C++11) |
함수 객체에 하나 이상의 인자를 결합해요. (함수 템플릿) |
is_bind_expression (C++11) |
객체가 std::bind 표현식이거나 그렇게 사용될 수 있음을 나타내요. (클래스 템플릿) |
is_placeholder (C++11) |
객체가 표준 플레이스홀더이거나 그렇게 사용될 수 있음을 나타내요. (클래스 템플릿) |
std::placeholders 네임스페이스에 정의된 _1, _2, _3, _4, ... 는 std::bind 표현식에서 결합되지 않은 인자를 나타내는 플레이스홀더예요. (C++11)
부정기 (Negators)
std::not_fn은 전달받은 호출 가능 객체의 결과를 부정하는 함수 객체를 만들어요.
| 구성 요소 | 설명 |
|---|---|
not_fn (C++17) |
보유한 함수 객체 결과의 보수를 반환하는 함수 객체를 만들어요. (함수 템플릿) |
검색기 (Searchers)
여러 문자열 검색 알고리즘을 구현한 검색기가 제공되며, 직접 사용하거나 std::search와 함께 사용할 수 있어요.
| 구성 요소 | 설명 |
|---|---|
default_searcher (C++17) |
표준 C++ 라이브러리 검색 알고리즘 구현이에요. (클래스 템플릿) |
boyer_moore_searcher (C++17) |
Boyer-Moore 검색 알고리즘 구현이에요. (클래스 템플릿) |
boyer_moore_horspool_searcher (C++17) |
Boyer-Moore-Horspool 검색 알고리즘 구현이에요. (클래스 템플릿) |
참조 래퍼 (Reference wrappers)
참조 래퍼는 참조 인자를 복사 가능한 함수 객체에 저장할 수 있게 해줘요.
| 구성 요소 | 설명 |
|---|---|
reference_wrapper (C++11) |
CopyConstructible 및 CopyAssignable 요구 사항을 만족하는 참조 래퍼예요. (클래스 템플릿) |
ref, cref (C++11) |
인자에서 타입을 추론하여 std::reference_wrapper를 만들어요. (함수 템플릿) |
unwrap_reference, unwrap_ref_decay (C++20) |
std::reference_wrapper에 감싸인 참조 타입을 얻어요. (클래스 템플릿) |
투명 함수 객체 (Transparent function objects)
연관 컨테이너와 비정렬 연관 컨테이너는 (C++20부터) 이종 검색(heterogeneous lookup)과 (C++23부터) 삭제(erasure) 연산을 제공해요. 다만 제공된 함수 객체 타입 T가 투명(transparent)해야 해요. 즉, 한정된 식별자 T::is_transparent가 유효하고 타입을 나타내야 해요. 표준 라이브러리의 모든 투명 함수 객체 타입은 중첩 타입 is_transparent를 정의해요. 사용자 정의 투명 함수 객체 타입은 T::is_transparent가 위 요구 사항을 만족하기만 하면 중첩 타입으로 직접 제공하지 않아도 돼요. (C++14부터)
연산자 함수 객체 (Operator function objects)
C++은 일반적인 산술 연산과 논리 연산을 나타내는 다음 함수 객체들을 정의해요. void 특수화는 인자에서 매개변수 타입과 반환 타입을 추론하며, 모두 투명해요. (C++14부터)
산술 연산
| 구성 요소 | 설명 |
|---|---|
plus |
x + y를 구현하는 함수 객체예요. (클래스 템플릿) |
plus<void> (C++14) |
매개변수와 반환 타입을 추론하여 x + y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
minus |
x - y를 구현하는 함수 객체예요. (클래스 템플릿) |
minus<void> (C++14) |
매개변수와 반환 타입을 추론하여 x - y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
multiplies |
x * y를 구현하는 함수 객체예요. (클래스 템플릿) |
multiplies<void> (C++14) |
매개변수와 반환 타입을 추론하여 x * y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
divides |
x / y를 구현하는 함수 객체예요. (클래스 템플릿) |
divides<void> (C++14) |
매개변수와 반환 타입을 추론하여 x / y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
modulus |
x % y를 구현하는 함수 객체예요. (클래스 템플릿) |
modulus<void> (C++14) |
매개변수와 반환 타입을 추론하여 x % y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
negate |
-x를 구현하는 함수 객체예요. (클래스 템플릿) |
negate<void> (C++14) |
매개변수와 반환 타입을 추론하여 -x를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
비교 연산
| 구성 요소 | 설명 |
|---|---|
equal_to |
x == y를 구현하는 함수 객체예요. (클래스 템플릿) |
equal_to<void> (C++14) |
매개변수와 반환 타입을 추론하여 x == y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
not_equal_to |
x != y를 구현하는 함수 객체예요. (클래스 템플릿) |
not_equal_to<void> (C++14) |
매개변수와 반환 타입을 추론하여 x != y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
greater |
x > y를 구현하는 함수 객체예요. (클래스 템플릿) |
greater<void> (C++14) |
매개변수와 반환 타입을 추론하여 x > y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
less |
x < y를 구현하는 함수 객체예요. (클래스 템플릿) |
less<void> (C++14) |
매개변수와 반환 타입을 추론하여 x < y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
greater_equal |
x >= y를 구현하는 함수 객체예요. (클래스 템플릿) |
greater_equal<void> (C++14) |
매개변수와 반환 타입을 추론하여 x >= y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
less_equal |
x <= y를 구현하는 함수 객체예요. (클래스 템플릿) |
less_equal<void> (C++14) |
매개변수와 반환 타입을 추론하여 x <= y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
논리 연산
| 구성 요소 | 설명 |
|---|---|
logical_and |
x && y를 구현하는 함수 객체예요. (클래스 템플릿) |
logical_and<void> (C++14) |
매개변수와 반환 타입을 추론하여 x && y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
logical_or |
x || y를 구현하는 함수 객체예요. (클래스 템플릿) |
logical_or<void> (C++14) |
매개변수와 반환 타입을 추론하여 x || y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
logical_not |
!x를 구현하는 함수 객체예요. (클래스 템플릿) |
logical_not<void> (C++14) |
매개변수와 반환 타입을 추론하여 !x를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
비트 연산
| 구성 요소 | 설명 |
|---|---|
bit_and |
x & y를 구현하는 함수 객체예요. (클래스 템플릿) |
bit_and<void> (C++14) |
매개변수와 반환 타입을 추론하여 x & y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
bit_or |
x | y를 구현하는 함수 객체예요. (클래스 템플릿) |
bit_or<void> (C++14) |
매개변수와 반환 타입을 추론하여 x | y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
bit_xor |
x ^ y를 구현하는 함수 객체예요. (클래스 템플릿) |
bit_xor<void> (C++14) |
매개변수와 반환 타입을 추론하여 x ^ y를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
bit_not (C++14) |
~x를 구현하는 함수 객체예요. (클래스 템플릿) |
bit_not<void> (C++14) |
매개변수와 반환 타입을 추론하여 ~x를 구현하는 함수 객체예요. (클래스 템플릿 특수화) |
제약된 비교 함수 객체 (Constrained comparison function objects)
다음 비교 함수 객체들은 제약(constrained)되어 있어요. 동등 비교 연산자(ranges::equal_to, ranges::not_equal_to)는 인자 타입이 equality_comparable_with를 만족해야 해요. 관계 연산자(ranges::less, ranges::greater, ranges::less_equal, ranges::greater_equal)는 인자 타입이 totally_ordered_with를 만족해야 해요. 삼방향 비교 연산자(compare_three_way)는 타입이 three_way_comparable_with를 모델링해야 해요. 이 모든 함수 객체는 투명해요. (C++20부터)
| 구성 요소 | 설명 |
|---|---|
ranges::equal_to (C++20) |
x == y를 구현하는 제약된 함수 객체예요. (클래스) |
ranges::not_equal_to (C++20) |
x != y를 구현하는 제약된 함수 객체예요. (클래스) |
ranges::less (C++20) |
x < y를 구현하는 제약된 함수 객체예요. (클래스) |
ranges::greater (C++20) |
x > y를 구현하는 제약된 함수 객체예요. (클래스) |
ranges::less_equal (C++20) |
x <= y를 구현하는 제약된 함수 객체예요. (클래스) |
ranges::greater_equal (C++20) |
x >= y를 구현하는 제약된 함수 객체예요. (클래스) |
compare_three_way (C++20) |
x <=> y를 구현하는 제약된 함수 객체예요. (클래스) |
헬퍼 항목 (Helper items)
다음 설명 전용 항목들은 표준 라이브러리의 여러 구성 요소에서 사용되지만, 표준 라이브러리의 인터페이스 일부는 아니에요. (C++26부터)
template < class Fn , class ... Args >
concept /*callable*/ = requires ( Fn && fn , Args && ... args ) {
std :: forward < Fn > ( fn )( std :: forward < Args > ( args )...);
};
template < class Fn , class ... Args >
concept /*nothrow-callable*/ = /*callable*/ < Fn , Args ... > && requires ( Fn && fn , Args && ... args ) {
{ std :: forward < Fn > ( fn )( std :: forward < Args > ( args )...) } noexcept ;
};
template < class Fn , class ... Args >
using /*call-result-t*/ = decltype ( std :: declval < Fn > ()( std :: declval < Args > ()...));
template < const auto & T >
using /*decayed-typeof*/ = decltype ( auto ( T ));
옛 바인더와 어댑터 (Old binders and adaptors)
초기 함수형 지원을 제공하던 여러 유틸리티는 폐기(deprecated)되고 제거(removed)되었어요.
기본 클래스
| 구성 요소 | 설명 |
|---|---|
unary_function (C++11에서 폐기, C++17에서 제거) |
어댑터 호환 단항 함수 기본 클래스예요. (클래스 템플릿) |
binary_function (C++11에서 폐기, C++17에서 제거) |
어댑터 호환 이항 함수 기본 클래스예요. (클래스 템플릿) |
바인더
| 구성 요소 | 설명 |
|---|---|
binder1st, binder2nd (C++11에서 폐기, C++17에서 제거) |
이항 함수와 그 인자 하나를 보관하는 함수 객체예요. (클래스 템플릿) |
bind1st, bind2nd (C++11에서 폐기, C++17에서 제거) |
이항 함수에 인자 하나를 결합해요. (함수 템플릿) |
함수 어댑터
| 구성 요소 | 설명 |
|---|---|
pointer_to_unary_function (C++11에서 폐기, C++17에서 제거) |
단항 함수 포인터를 위한 어댑터 호환 래퍼예요. (클래스 템플릿) |
pointer_to_binary_function (C++11에서 폐기, C++17에서 제거) |
이항 함수 포인터를 위한 어댑터 호환 래퍼예요. (클래스 템플릿) |
ptr_fun (C++11에서 폐기, C++17에서 제거) |
함수 포인터로부터 어댑터 호환 함수 객체 래퍼를 만들어요. (함수 템플릿) |
mem_fun_t, mem_fun1_t, const_mem_fun_t, const_mem_fun1_t (C++11에서 폐기, C++17에서 제거) |
객체 포인터로 호출할 수 있는 0항 또는 단항 멤버 함수 포인터용 래퍼예요. (클래스 템플릿) |
mem_fun (C++11에서 폐기, C++17에서 제거) |
객체 포인터로 호출할 수 있는 멤버 함수 포인터 래퍼를 만들어요. (함수 템플릿) |
mem_fun_ref_t, mem_fun1_ref_t, const_mem_fun_ref_t, const_mem_fun1_ref_t (C++11에서 폐기, C++17에서 제거) |
객체 참조로 호출할 수 있는 0항 또는 단항 멤버 함수 포인터용 래퍼예요. (클래스 템플릿) |
mem_fun_ref (C++11에서 폐기, C++17에서 제거) |
객체 참조로 호출할 수 있는 멤버 함수 포인터 래퍼를 만들어요. (함수 템플릿) |
unary_negate (C++17에서 폐기, C++20에서 제거) |
보유한 단항 술어의 보수를 반환하는 래퍼 함수 객체예요. (클래스 템플릿) |
binary_negate (C++17에서 폐기, C++20에서 제거) |
보유한 이항 술어의 보수를 반환하는 래퍼 함수 객체예요. (클래스 템플릿) |
not1 (C++17에서 폐기, C++20에서 제거) |
사용자 정의 std::unary_negate 객체를 만들어요. (함수 템플릿) |
not2 (C++17에서 폐기, C++20에서 제거) |
사용자 정의 std::binary_negate 객체를 만들어요. (함수 템플릿) |
결함 보고서 (Defect reports)
다음 동작 변경 결함 보고서는 이전에 발표된 C++ 표준에 소급 적용되었어요.
| DR | 적용 대상 | 발표된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 185 | C++98 | 함수 객체를 사용하면 프로그램 효율이 향상된다고 명시 | 해당 주장 제거 |
| LWG 660 | C++98 | 비트 연산용 함수 객체가 없음 | 추가됨 |
| LWG 2149 | C++98 | 인자를 하나 또는 두 개 받는 함수 객체가 인자 타입과 결과 타입을 나타내는 중첩 타입을 제공해야 함 | 요구하지 않음 |
| LWG 2219 | C++11 | INVOKE가 std::reference_wrapper를 올바르게 처리하지 못함 |
올바르게 처리함 |
| LWG 2420 | C++11 | INVOKE<R>가 R이 void일 때 반환 값을 버리지 않음 |
이 경우 반환 값을 버림 |
| LWG 2926 (P0604R0) | C++11 | 반환 타입 R을 사용하는 INVOKE 연산 문법이 INVOKE(f, t1, t2, ..., tN, R)이었음 |
INVOKE<R>(f, t1, t2, ..., tN)으로 변경 |
| LWG 3655 | C++11 | LWG 2219 해결로 인해 INVOKE가 공용체(union)를 올바르게 처리하지 못함 |
올바르게 처리함 |