/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_FunctionTypeTraits_h #define mozilla_FunctionTypeTraits_h #include /* for size_t */ namespace mozilla { // Main FunctionTypeTraits declaration, taking one template argument. // // Given a function type, FunctionTypeTraits will expose the following members: // - ReturnType: Return type. // - arity: Number of parameters (size_t). // - ParameterType: Type of the Nth** parameter, 0-indexed. // // ** `ParameterType` with `N` >= `arity` is allowed and gives `void`. // This prevents compilation errors when trying to access a type outside of the // function's parameters, which is useful for parameters checks, e.g.: // template // auto foo(F&&) // -> enable_if(FunctionTypeTraits::arity == 1 && // is_same::template ParameterType<0>, // int>::value, // void) // { // // This function will only be enabled if `F` takes one `int`. // // Without the permissive ParameterType, it wouldn't even compile. // // Note: FunctionTypeTraits does not work with generic lambdas `[](auto&) {}`, // because parameter types cannot be known until an actual invocation when types // are inferred from the given arguments. template struct FunctionTypeTraits; // Remove reference and pointer wrappers, if any. template struct FunctionTypeTraits : FunctionTypeTraits {}; template struct FunctionTypeTraits : FunctionTypeTraits {}; template struct FunctionTypeTraits : FunctionTypeTraits {}; // Extract `operator()` function from callables (e.g. lambdas, std::function). template struct FunctionTypeTraits : FunctionTypeTraits {}; namespace detail { template struct SafePackElement; template struct SafePackElement { using type = void; }; template struct SafePackElement<0, A, As...> { using type = A; }; template struct SafePackElement : SafePackElement {}; template using SafePackElementType = typename SafePackElement::type; } // namespace detail // Specialization for free functions. template struct FunctionTypeTraits { using ReturnType = R; static constexpr size_t arity = sizeof...(As); template using ParameterType = detail::SafePackElementType; }; // Specialization for non-const member functions. template struct FunctionTypeTraits : FunctionTypeTraits {}; // Specialization for const member functions. template struct FunctionTypeTraits : FunctionTypeTraits {}; #ifdef NS_HAVE_STDCALL // Specialization for __stdcall free functions. template struct FunctionTypeTraits : FunctionTypeTraits { }; // Specialization for __stdcall non-const member functions. template struct FunctionTypeTraits : FunctionTypeTraits {}; // Specialization for __stdcall const member functions. template struct FunctionTypeTraits : FunctionTypeTraits {}; #endif // NS_HAVE_STDCALL } // namespace mozilla #endif // mozilla_FunctionTypeTraits_h