types_is_function

types_is_function (함수 타입 판별)

std::is_function은 주어진 타입 T가 함수 타입인지 확인하는 UnaryTypeTrait입니다. 함수 타입에는 일반 함수, 멤버 함수 등이 포함되지만, std::function, 람다, operator()를 오버로드한 클래스, 함수 포인터는 포함되지 않아요. 이 페이지에서는 std::is_function의 정의, 멤버, 구현 예시를 살펴봅니다.

출처: cppreference

본문

헤더에 정의

Defined in header <type_traits>
template < class T > struct is_function ; (C++11부터)

std::is_function은 T가 함수 타입인지 확인해요. std::function, 람다, operator()를 오버로드한 클래스, 함수 포인터 같은 타입은 함수 타입으로 간주하지 않습니다. T가 함수 타입이면 멤버 상수 valuetrue이고, 그렇지 않으면 false예요.

프로그램에서 std::is_function 또는 std::is_function_v에 대한 특수화를 추가하면 동작이 정의되지 않습니다.

템플릿 매개변수

T - 확인할 타입

헬퍼 변수 템플릿

template < class T > constexpr bool is_function_v = is_function < T >:: value ; (C++17부터)

std::integral_constant에서 상속됨

멤버 상수

value [static] T가 함수 타입이면 true, 아니면 false (공용 정적 멤버 상수)

멤버 함수

operator bool 객체를 bool로 변환하고 value를 반환해요 (공용 멤버 함수)
operator() (C++14) value를 반환해요 (공용 멤버 함수)

멤버 타입

Type Definition
value_type bool
type std :: integral_constant < bool , value >

Notes

std::is_function은 훨씬 간단하게 구현할 수 있어요. libc++, libstdc++, MS STL의 최신 버전에서는 다음과 유사한 구현을 사용합니다.

template<class T>
struct is_function : std::integral_constant<
    bool,
    !std::is_const<const T>::value && !std::is_reference<T>::value
> {};

아래 구현은 다양한 함수 타입을 보여 주기 위한 교육용 예시입니다.

가능한 구현

// primary template
template<class>
struct is_function : std::false_type {};

// specialization for regular functions
template<class Ret, class... Args>
struct is_function<Ret(Args...)> : std::true_type {};

// specialization for variadic functions such as std::printf
template<class Ret, class... Args>
struct is_function<Ret(Args......)> : std::true_type {};

// specialization for function types that have cv-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...) const> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) volatile> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const volatile> : std::true_type {};

// specialization for function types that have ref-qualifiers
template<class Ret, class... Args>
struct is_function<Ret(Args...) &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) volatile &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const volatile &> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) volatile &&> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const volatile &&> : std::true_type {};

// specializations for noexcept versions of all the above (C++17 and later)
template<class Ret, class... Args>
struct is_function<Ret(Args...) noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) volatile noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const volatile noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) & noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const & noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile & noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile & noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) & noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const & noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) volatile & noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const volatile & noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) && noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const && noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) volatile && noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args...) const volatile && noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) && noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const && noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) volatile && noexcept> : std::true_type {};
template<class Ret, class... Args>
struct is_function<Ret(Args......) const volatile && noexcept> : std::true_type {};

예제

#include <functional>
#include <type_traits>

int f();
static_assert(std::is_function_v<decltype(f)>);

static_assert(std::is_function_v<int(int)>);
static_assert(!std::is_function_v<int>);
static_assert(!std::is_function_v<decltype([]{})>);
static_assert(!std::is_function_v<std::function<void()>>);

struct O { void operator()() {} };
static_assert(std::is_function_v<O()>);

struct A
{
    static int foo();
    int fun() const&;
};
static_assert(!std::is_function_v<A>);
static_assert(std::is_function_v<decltype(A::foo)>);
static_assert(!std::is_function_v<decltype(&A::fun)>);

template<typename>
struct PM_traits {};
template<class T, class U>
struct PM_traits<U T::*> { using member_type = U; };

int main()
{
    using T = PM_traits<decltype(&A::fun)>::member_type; // T is int() const&
    static_assert(std::is_function_v<T>);
}

같이 보기

is_invocable, is_invocable_r, is_nothrow_invocable, is_nothrow_invocable_r (C++17) 주어진 인자 타입으로 (std::invoke처럼) 호출할 수 있는 타입인지 확인해요 (클래스 템플릿)
is_object (C++11) 타입이 객체 타입인지 확인해요 (클래스 템플릿)
is_class (C++11) 타입이 비공용체 클래스 타입인지 확인해요 (클래스 템플릿)
is_function_type (C++26) 반영된 타입이 함수 타입인지 확인해요 (함수)

더 알아보기 (Learn more)

cppreference