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가 함수 타입이면 멤버 상수 value는 true이고, 그렇지 않으면 false예요.
프로그램에서 std::is_function 또는 std::is_function_v에 대한 특수화를 추가하면 동작이 정의되지 않습니다.
템플릿 매개변수
헬퍼 변수 템플릿
| 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