home | help
std::is_function(3)	       C++ Standard Libary	     std::is_function(3)

NAME
     std::is_function - std::is_function

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

	std::is_function is a UnaryTypeTrait.

	Checks	whether T is a function type. Types like std::function, lambdas,
     classes with
	overloaded operator() and pointers to functions don't count as	function
     types.
	Provides  the  member  constant  value which is equal to true, if T is a
     function type.
	Otherwise, value is equal to false.

	If  the   program   adds   specializations   for   std::is_function   or
     std::is_function_v, the
	behavior is undefined.

Template parameters
	T - a type to check

	Helper variable template

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

     Inherited from std::integral_constant

Member constants
	value	 true if T is a function type, false otherwise
	[static] (public static member constant)

Member functions
	operator bool converts the object to bool, returns value
		      (public member function)
	operator()    returns value
	(C++14)       (public member function)

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

Notes
	std::is_function can be implemented in much  simpler  ways.  Implementa-
     tions similar to
	the  following	one are used by new versions of libc++, libstdc++ and MS
     STL:

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

	The implementation shown below is for pedagogical purposes, since it ex-
     hibits the
	myriad kinds of function types.

Possible implementation
	// 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 {};

Example
     // Run this code

      #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>);
      }

See also
	is_invocable
	is_invocable_r	       checks if  a  type  can	be  invoked  (as  if  by
     std::invoke) with
	is_nothrow_invocable   the given argument types
	is_nothrow_invocable_r (class template)
	(C++17)
	is_object	       checks if a type is an object type
	(C++11) 	       (class template)
	is_class	       checks if a type is a non-union class type
	(C++11) 	       (class template)

http://cppreference.com 	   2024.06.10		     std::is_function(3)

home | help