From fa9a0a0683bbfa968b19ed5170538a56a01f889c Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Mon, 13 Dec 2021 00:05:09 -0800 Subject: [PATCH] [lib][cpp] add a type_traits header mostly for std::move and friends. --- lib/libcpp/include/type_traits | 502 +++++++++++++++++++++++++++++++++ 1 file changed, 502 insertions(+) create mode 100644 lib/libcpp/include/type_traits diff --git a/lib/libcpp/include/type_traits b/lib/libcpp/include/type_traits new file mode 100644 index 00000000..365f1597 --- /dev/null +++ b/lib/libcpp/include/type_traits @@ -0,0 +1,502 @@ +// Copyright 2016 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +namespace std { + +template +struct integral_constant { + static constexpr T value = v; + + using value_type = T; + using type = integral_constant; +}; + +using true_type = integral_constant; +using false_type = integral_constant; + +// is_void: +template +struct is_void : false_type {}; + +template <> +struct is_void : true_type {}; + +template <> +struct is_void : true_type {}; + +template <> +struct is_void : true_type {}; + +template <> +struct is_void : true_type {}; + +// is_null_pointer: +template +struct is_null_pointer : false_type {}; + +template <> +struct is_null_pointer : true_type {}; + +template <> +struct is_null_pointer : true_type {}; + +template <> +struct is_null_pointer : true_type {}; + +template <> +struct is_null_pointer : true_type {}; + +// is_const: + +template +struct is_const : false_type {}; + +template +struct is_const : true_type {}; + +// is_lvalue_reference: + +template +struct is_lvalue_reference : false_type {}; + +template +struct is_lvalue_reference : true_type {}; + +// is_rvalue_reference: + +template +struct is_rvalue_reference : false_type {}; + +template +struct is_rvalue_reference : true_type {}; + +// is_reference: +template +struct is_reference : false_type {}; + +template +struct is_reference : true_type {}; + +template +struct is_reference : true_type {}; + +// remove_reference: + +template +struct remove_reference { + using type = T; +}; + +template +struct remove_reference { + using type = T; +}; + +template +struct remove_reference { + using type = T; +}; + +// remove_pointer: + +template +struct remove_pointer { + using type = T; +}; + +template +struct remove_pointer { + using type = T; +}; + +// remove_const: + +template +struct remove_const { + typedef T type; +}; + +template +struct remove_const { + typedef T type; +}; + +// remove_volatile: + +template +struct remove_volatile { + typedef T type; +}; + +template +struct remove_volatile { + typedef T type; +}; + +// remove_cv: + +template +struct remove_cv { + typedef typename remove_volatile::type>::type type; +}; + +// remove_extent: + +template +struct remove_extent { + using type = T; +}; + +template +struct remove_extent { + using type = T; +}; + +// Avoid having to pull in a header to name size_t; just use sizeof to +// get at it. +template +struct remove_extent { + using type = T; +}; + +// move + +template +constexpr typename remove_reference::type&& move(T&& t) { + return static_cast::type&&>(t); +} + +// forward: + +template +constexpr T&& forward(typename remove_reference::type& t) { + return static_cast(t); +} + +template +constexpr T&& forward(typename remove_reference::type&& t) { + static_assert(!is_lvalue_reference::value, "bad std::forward call"); + return static_cast(t); +} + +// is_same: + +template struct is_same : false_type {}; +template struct is_same : true_type {}; + +// enable_if: + +template struct enable_if { }; +template struct enable_if { + typedef T type; +}; + +// conditional: + +template +struct conditional { typedef T type; }; + +template +struct conditional { typedef F type; }; + +// is_integral. By default, T is not integral (aka, not an integer) +template +struct is_integral : false_type {}; + +// Specializations. Every basic integral type needs to be called out. +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; +template <> struct is_integral : true_type {}; + +// is_floating_point. By default, T is not a floating point type. +template +struct is_floating_point : false_type {}; + +// Specializations. Every basic floating point type needs to be called out. +template <> struct is_floating_point : true_type {}; +template <> struct is_floating_point : true_type {}; +template <> struct is_floating_point : true_type {}; + +// Arithmetic data types are either floats or integers +template +struct is_arithmetic : + integral_constant::value || is_floating_point::value> { }; + +namespace internal { + +template::value> +struct is_signed : integral_constant {}; +template +struct is_signed : std::false_type {}; + +template::value> +struct is_unsigned : integral_constant {}; +template +struct is_unsigned : std::false_type {}; + +template::value> +struct is_signed_integer : integral_constant {}; +template +struct is_signed_integer : std::false_type {}; + +template::value> +struct is_unsigned_integer : integral_constant {}; +template +struct is_unsigned_integer : std::false_type {}; + +} // namespace internal + +template +struct is_signed : internal::is_signed::type {}; + +template +struct is_unsigned : internal::is_unsigned::type {}; + +template +struct is_signed_integer : internal::is_signed_integer::type {}; + +template +struct is_unsigned_integer : internal::is_unsigned_integer::type {}; + +// is_enum is a builtin +template +struct is_enum : integral_constant { }; + +// is_pod is a builtin +template +struct is_pod : integral_constant { }; + +// is_standard_layout is a builtin +template +struct is_standard_layout : integral_constant { }; + +// underlying_type is a builtin +template +struct underlying_type { + using type = __underlying_type(T); +}; + +// match_cv: match_cv::type is DestType cv-qualified in the same way as SrcType. + +// Primary template: +template +struct match_cv { + using type = typename remove_cv::type; +}; + +// Specializations for const/volatile/const volatile: +template +struct match_cv { + using type = typename remove_cv::type const; +}; +template +struct match_cv { + using type = typename remove_cv::type volatile; +}; +template +struct match_cv { + using type = typename remove_cv::type const volatile; +}; + +// is_class builtin +template +struct is_class : public integral_constant { }; + +// is_union builtin +template +struct is_union : public integral_constant { }; + +// is_base_of builtin +template +struct is_base_of : public integral_constant { }; + +// has_virtual_destructor +template +struct has_virtual_destructor : public integral_constant { }; + +// has_trivial_destructor +template +struct has_trivial_destructor : public integral_constant { }; + +// is_pointer +namespace internal { +template +struct is_pointer : public false_type { }; + +template +struct is_pointer : public true_type { }; +} // namespace internal + +template +struct is_pointer : + public integral_constant::type>::value> { }; + +// is_convertible_pointer +// +// Note: this is a simplified version of std::is_convertible. Whereas +// std::is_convertible will check to see if any two types are implicitly +// convertible, is_convertible_pointer will only check to see if two pointer +// types are implicitly convertible. Additionally, no explicit support or tests +// have been added for function pointers conversion. +template +struct is_convertible_pointer { +private: + static true_type test(To); + static false_type test(...); + static From make_from_type(); + +public: + static constexpr bool value = + is_pointer::value && + is_pointer::value && + decltype(test(make_from_type()))::value; +}; + +// Macro for defining a trait that checks if a type T has a method with the +// given name. This is not as strong as using is_same to check function +// signatures, but checking this trait first gives a better static_assert +// message than the compiler warnings from is_same if the function doesn't +// exist. +// Note that the resulting trait_name will be in the namespace where the macro +// is used. +// +// Example: +// +// DECLARE_HAS_MEMBER_FN(has_bar, Bar); +// template +// class Foo { +// static_assert(has_bar::value, "Foo classes must implement Bar()!"); +// // TODO: use 'if constexpr' to avoid this next static_assert once c++17 +// lands. +// static_assert(is_same::value, +// "Bar must be a non-static member function with signature " +// "'void Bar(int)', and must be visible to Foo (either " +// "because it is public, or due to friendship)."); +// }; +#define DECLARE_HAS_MEMBER_FN(trait_name, fn_name) \ +template \ +struct trait_name { \ +private: \ + template static ::std::true_type test( decltype(&C::fn_name) ); \ + template static ::std::false_type test(...); \ + \ +public: \ + static constexpr bool value = decltype(test(nullptr))::value; \ +} + +// Similar to DECLARE_HAS_MEMBER_FN but also checks the function signature. +// This is especially useful when the desired function may be overloaded. +// The signature must take the form "ResultType (C::*)(ArgType1, ArgType2)". +// +// Example: +// +// DECLARE_HAS_MEMBER_FN_WITH_SIGNATURE(has_c_str, c_str, const char* (C::*)() const); +#define DECLARE_HAS_MEMBER_FN_WITH_SIGNATURE(trait_name, fn_name, sig) \ +template \ +struct trait_name { \ +private: \ + template static ::std::true_type test( decltype(static_cast(&C::fn_name)) ); \ + template static ::std::false_type test(...); \ + \ +public: \ + static constexpr bool value = decltype(test(nullptr))::value; \ +} + +namespace internal { + +template +struct make_void { + using type = void; +}; + +} // namespace internal + +// Utility type for SFINAE expression evaluation, equivalent to C++17 std::void_t. +template +using void_t = typename internal::make_void::type; + +// is_function: + +// Morally, is_function could be implemented in the same style as +// e.g. is_reference: a base case of false, and specializations of +// true for every kind of function. However, listing all of those +// cases is brittle and language version dependent. For instance, +// C++17 makes noexcept specifiers as part of the type. + +// Instead, this implementation uses a pair of tricky overloaded +// functions to detect every type that _isn't_ a function. This +// includes: +// - objects (classes, unions, and primitives) (including incomplete types) +// - references (including references to functions) +// - nullptr_t +// - void +// - pointers (including pointers to functions) +// - pointers to members +// - arrays of both complete and incomplete type + +namespace internal { + +// This leaves pointers, pointer-to-members, arrays, and functions. +template +struct is_object_void_reference_or_null_pointer { + static constexpr bool value = + is_class::value || + is_union::value || + is_void::value || + is_reference::value || + is_null_pointer::value; +}; + +struct dummy {}; + +struct func_tag {}; + +struct nonfunc_tag {}; + +template +func_tag choose(T*); + +template +func_tag choose(dummy); + +template +nonfunc_tag choose(...); + +template +T& make(int); + +template +dummy make(...); + +} // namespace internal + +template ::value> +struct is_function : public integral_constant(internal::make(0))) + >::value> { +}; + +template +struct is_function : public false_type { +}; + +} // namespace std +// vim: syntax=cpp