utility_functional

utility_functional (함수 객체)

함수 객체는 함수 호출 연산자(function call operator)가 정의된 모든 객체를 의미해요. C++은 다양한 내장 함수 객체를 제공할 뿐만 아니라, 새로운 함수 객체를 생성하고 조작할 수 있는 기능도 함께 지원해요.

출처: cppreference

본문

함수 객체란?

함수 객체는 operator()를 정의한 객체예요. 일반 함수처럼 호출할 수 있으면서도, 객체이기 때문에 상태를 가질 수 있고 템플릿 인자로 전달하기도 쉬워요. C++ 표준 라이브러리의 많은 알고리즘과 어댑터가 함수 객체를 사용해요.

함수 호출 (Function invocation)

설명 전용 연산인 INVOKE(f, arg_0, arg_1, arg_2, ..., arg_N)은 다음과 같이 정의돼요. Objarg_0의 비한정 타입, 즉 std::remove_cv<std::remove_reference<decltype(arg_0)>::type>::type이고, objObj 타입의 객체예요.

  • f가 클래스 C의 멤버 함수 포인터라면:
    • std::is_same<C, Obj>::value || std::is_base_of<C, Obj>::valuetrue이면 (obj.*f)(arg_1, arg_2, ..., arg_N)로 호출해요.
    • Objstd::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>::valuetrue이면 obj.*mptr로 접근해요.
    • Objstd::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로 암묵적으로 변환해요.
  • Actualdecltype(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::invokestd::invoke_r(C++23부터)은 INVOKEINVOKE<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_frontstd::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) CopyConstructibleCopyAssignable 요구 사항을 만족하는 참조 래퍼예요. (클래스 템플릿)
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 INVOKEstd::reference_wrapper를 올바르게 처리하지 못함 올바르게 처리함
LWG 2420 C++11 INVOKE<R>Rvoid일 때 반환 값을 버리지 않음 이 경우 반환 값을 버림
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)를 올바르게 처리하지 못함 올바르게 처리함

더 알아보기 (Learn more)

cppreference