+/*
+ * IsZeroInitializable describes the property that default construction is the
+ * same as memset(dst, 0, sizeof(T)).
+ */
+
+namespace traits_detail {
+
+#define FOLLY_HAS_TRUE_XXX(name) \
+ FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(has_##name, name); \
+ template <class T> \
+ struct name##_is_true : std::is_same<typename T::name, std::true_type> {}; \
+ template <class T> \
+ struct has_true_##name : std::conditional< \
+ has_##name<T>::value, \
+ name##_is_true<T>, \
+ std::false_type>::type {};
+
+FOLLY_HAS_TRUE_XXX(IsRelocatable)
+FOLLY_HAS_TRUE_XXX(IsZeroInitializable)
+FOLLY_HAS_TRUE_XXX(IsTriviallyCopyable)
+
+#undef FOLLY_HAS_TRUE_XXX
+
+// Older versions of libstdc++ do not provide std::is_trivially_copyable
+#if defined(__clang__) && !defined(_LIBCPP_VERSION)
+template <class T>
+struct is_trivially_copyable
+ : std::integral_constant<bool, __is_trivially_copyable(T)> {};
+#elif defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
+template <class T>
+struct is_trivially_copyable : std::is_trivial<T> {};
+#else
+template <class T>
+using is_trivially_copyable = std::is_trivially_copyable<T>;
+#endif
+} // namespace traits_detail
+
+struct Ignore {
+ Ignore() = default;
+ template <class T>
+ constexpr /* implicit */ Ignore(const T&) {}
+ template <class T>
+ const Ignore& operator=(T const&) const { return *this; }
+};
+
+template <class...>
+using Ignored = Ignore;
+
+namespace traits_detail_IsEqualityComparable {
+Ignore operator==(Ignore, Ignore);
+
+template <class T, class U = T>
+struct IsEqualityComparable
+ : std::is_convertible<
+ decltype(std::declval<T>() == std::declval<U>()),
+ bool
+ > {};
+} // namespace traits_detail_IsEqualityComparable
+
+/* using override */ using traits_detail_IsEqualityComparable::
+ IsEqualityComparable;
+
+namespace traits_detail_IsLessThanComparable {
+Ignore operator<(Ignore, Ignore);
+
+template <class T, class U = T>
+struct IsLessThanComparable
+ : std::is_convertible<
+ decltype(std::declval<T>() < std::declval<U>()),
+ bool
+ > {};
+} // namespace traits_detail_IsLessThanComparable
+
+/* using override */ using traits_detail_IsLessThanComparable::
+ IsLessThanComparable;
+
+namespace traits_detail_IsNothrowSwappable {
+#if defined(__cpp_lib_is_swappable) || (_CPPLIB_VER && _HAS_CXX17)
+// MSVC 2015+ already implements the C++17 P0185R1 proposal which
+// adds std::is_nothrow_swappable, so use it instead if C++17 mode
+// is enabled.
+template <typename T>
+using IsNothrowSwappable = std::is_nothrow_swappable<T>;
+#elif _CPPLIB_VER
+// MSVC 2015+ defines the base even if C++17 is disabled, and
+// MSVC 2015 has issues with our fallback implementation due to
+// over-eager evaluation of noexcept.
+template <typename T>
+using IsNothrowSwappable = std::_Is_nothrow_swappable<T>;
+#else
+/* using override */ using std::swap;
+
+template <class T>
+struct IsNothrowSwappable
+ : std::integral_constant<bool,
+ std::is_nothrow_move_constructible<T>::value &&
+ noexcept(swap(std::declval<T&>(), std::declval<T&>()))
+ > {};
+#endif
+} // namespace traits_detail_IsNothrowSwappable
+
+/* using override */ using traits_detail_IsNothrowSwappable::IsNothrowSwappable;
+
+template <class T> struct IsTriviallyCopyable
+ : std::conditional<
+ traits_detail::has_IsTriviallyCopyable<T>::value,
+ traits_detail::has_true_IsTriviallyCopyable<T>,
+ traits_detail::is_trivially_copyable<T>
+ >::type {};
+
+template <class T> struct IsRelocatable
+ : std::conditional<
+ traits_detail::has_IsRelocatable<T>::value,
+ traits_detail::has_true_IsRelocatable<T>,
+ // TODO add this line (and some tests for it) when we upgrade to gcc 4.7
+ //std::is_trivially_move_constructible<T>::value ||
+ IsTriviallyCopyable<T>
+ >::type {};
+
+template <class T> struct IsZeroInitializable
+ : std::conditional<
+ traits_detail::has_IsZeroInitializable<T>::value,
+ traits_detail::has_true_IsZeroInitializable<T>,
+ std::integral_constant<bool, !std::is_class<T>::value>
+ >::type {};
+
+template <typename...>
+struct Conjunction : std::true_type {};
+template <typename T>
+struct Conjunction<T> : T {};
+template <typename T, typename... TList>
+struct Conjunction<T, TList...>
+ : std::conditional<T::value, Conjunction<TList...>, T>::type {};
+
+template <typename...>
+struct Disjunction : std::false_type {};
+template <typename T>
+struct Disjunction<T> : T {};
+template <typename T, typename... TList>
+struct Disjunction<T, TList...>
+ : std::conditional<T::value, T, Disjunction<TList...>>::type {};
+
+template <typename T>
+struct Negation : std::integral_constant<bool, !T::value> {};
+
+template <bool... Bs>
+struct Bools {
+ using valid_type = bool;
+ static constexpr std::size_t size() {
+ return sizeof...(Bs);
+ }
+};
+
+// Lighter-weight than Conjunction, but evaluates all sub-conditions eagerly.
+template <class... Ts>
+struct StrictConjunction
+ : std::is_same<Bools<Ts::value...>, Bools<(Ts::value || true)...>> {};
+
+template <class... Ts>
+struct StrictDisjunction
+ : Negation<
+ std::is_same<Bools<Ts::value...>, Bools<(Ts::value && false)...>>
+ > {};