1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 6 #pragma once 7 8 #include <type_traits> 9 #include <utility> 10 11 namespace folly { 12 13 #if !defined(_MSC_VER) 14 template <class T> 15 struct is_trivially_copyable 16 : std::integral_constant<bool, __has_trivial_copy(T)> {}; 17 #else 18 template <class T> 19 using is_trivially_copyable = std::is_trivially_copyable<T>; 20 #endif 21 22 /*** 23 * _t 24 * 25 * Instead of: 26 * 27 * using decayed = typename std::decay<T>::type; 28 * 29 * With the C++14 standard trait aliases, we could use: 30 * 31 * using decayed = std::decay_t<T>; 32 * 33 * Without them, we could use: 34 * 35 * using decayed = _t<std::decay<T>>; 36 * 37 * Also useful for any other library with template types having dependent 38 * member types named `type`, like the standard trait types. 39 */ 40 template <typename T> 41 using _t = typename T::type; 42 43 /** 44 * type_t 45 * 46 * A type alias for the first template type argument. `type_t` is useful for 47 * controlling class-template and function-template partial specialization. 48 * 49 * Example: 50 * 51 * template <typename Value> 52 * class Container { 53 * public: 54 * template <typename... Args> 55 * Container( 56 * type_t<in_place_t, decltype(Value(std::declval<Args>()...))>, 57 * Args&&...); 58 * }; 59 * 60 * void_t 61 * 62 * A type alias for `void`. `void_t` is useful for controling class-template 63 * and function-template partial specialization. 64 * 65 * Example: 66 * 67 * // has_value_type<T>::value is true if T has a nested type `value_type` 68 * template <class T, class = void> 69 * struct has_value_type 70 * : std::false_type {}; 71 * 72 * template <class T> 73 * struct has_value_type<T, folly::void_t<typename T::value_type>> 74 * : std::true_type {}; 75 */ 76 77 /** 78 * There is a bug in libstdc++, libc++, and MSVC's STL that causes it to 79 * ignore unused template parameter arguments in template aliases and does not 80 * cause substitution failures. This defect has been recorded here: 81 * http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558. 82 * 83 * This causes the implementation of std::void_t to be buggy, as it is likely 84 * defined as something like the following: 85 * 86 * template <typename...> 87 * using void_t = void; 88 * 89 * This causes the compiler to ignore all the template arguments and does not 90 * help when one wants to cause substitution failures. Rather declarations 91 * which have void_t in orthogonal specializations are treated as the same. 92 * For example, assuming the possible `T` types are only allowed to have 93 * either the alias `one` or `two` and never both or none: 94 * 95 * template <typename T, 96 * typename std::void_t<std::decay_t<T>::one>* = nullptr> 97 * void foo(T&&) {} 98 * template <typename T, 99 * typename std::void_t<std::decay_t<T>::two>* = nullptr> 100 * void foo(T&&) {} 101 * 102 * The second foo() will be a redefinition because it conflicts with the first 103 * one; void_t does not cause substitution failures - the template types are 104 * just ignored. 105 */ 106 107 namespace traits_detail { 108 template <class T, class...> 109 struct type_t_ { 110 using type = T; 111 }; 112 } // namespace traits_detail 113 114 template <class T, class... Ts> 115 using type_t = typename traits_detail::type_t_<T, Ts...>::type; 116 template <class... Ts> 117 using void_t = type_t<void, Ts...>; 118 119 /** 120 * A type trait to remove all const volatile and reference qualifiers on a 121 * type T 122 */ 123 template <typename T> 124 struct remove_cvref { 125 using type = 126 typename std::remove_cv<typename std::remove_reference<T>::type>::type; 127 }; 128 template <typename T> 129 using remove_cvref_t = typename remove_cvref<T>::type; 130 131 template <class T> 132 struct IsNothrowSwappable 133 : std::integral_constant< 134 bool, 135 std::is_nothrow_move_constructible<T>::value&& noexcept( 136 std::swap(std::declval<T&>(), std::declval<T&>()))> {}; 137 138 template <typename...> 139 struct Conjunction : std::true_type {}; 140 template <typename T> 141 struct Conjunction<T> : T {}; 142 template <typename T, typename... TList> 143 struct Conjunction<T, TList...> 144 : std::conditional<T::value, Conjunction<TList...>, T>::type {}; 145 146 template <typename T> 147 struct Negation : std::integral_constant<bool, !T::value> {}; 148 149 template <std::size_t I> 150 using index_constant = std::integral_constant<std::size_t, I>; 151 152 } // namespace folly 153