template <typename TTheClass_> \
struct classname##__folly_traits_impl__ { \
template <typename UTheClass_> \
- static std::true_type test(typename UTheClass_::type_name*); \
+ static constexpr bool test(typename UTheClass_::type_name*) { \
+ return true; \
+ } \
template <typename> \
- static std::false_type test(...); \
+ static constexpr bool test(...) { \
+ return false; \
+ } \
}; \
template <typename TTheClass_> \
- using classname = decltype( \
+ using classname = typename std::conditional< \
classname##__folly_traits_impl__<TTheClass_>::template test<TTheClass_>( \
- nullptr))
+ nullptr), \
+ std::true_type, \
+ std::false_type>::type;
#define FOLLY_CREATE_HAS_MEMBER_FN_TRAITS_IMPL(classname, func_name, cv_qual) \
template <typename TTheClass_, typename RTheReturn_, typename... TTheArgs_> \
namespace folly {
+/***
+ * _t
+ *
+ * Instead of:
+ *
+ * using decayed = typename std::decay<T>::type;
+ *
+ * With the C++14 standard trait aliases, we could use:
+ *
+ * using decayed = std::decay_t<T>;
+ *
+ * Without them, we could use:
+ *
+ * using decayed = _t<std::decay<T>>;
+ *
+ * Also useful for any other library with template types having dependent
+ * member types named `type`, like the standard trait types.
+ */
+template <typename T>
+using _t = typename T::type;
+
+/**
+ * void_t
+ *
+ * A type alias for `void`. `void_t` is useful for controling class-template
+ * partial specialization.
+ *
+ * Example:
+ *
+ * // has_value_type<T>::value is true if T has a nested type `value_type`
+ * template <class T, class = void>
+ * struct has_value_type
+ * : std::false_type {};
+ *
+ * template <class T>
+ * struct has_value_type<T, folly::void_t<typename T::value_type>>
+ * : std::true_type {};
+ */
+#if defined(__cpp_lib_void_t) || defined(_MSC_VER)
+
+/* using override */ using std::void_t;
+
+#else // defined(__cpp_lib_void_t) || defined(_MSC_VER)
+
+namespace traits_detail {
+template <class...>
+struct void_t_ {
+ using type = void;
+};
+} // namespace traits_detail
+
+template <class... Ts>
+using void_t = _t<traits_detail::void_t_<Ts...>>;
+
+#endif // defined(__cpp_lib_void_t) || defined(_MSC_VER)
+
/**
* IsRelocatable<T>::value describes the ability of moving around
* memory a value of type T by using memcpy (as opposed to the
IsLessThanComparable;
namespace traits_detail_IsNothrowSwappable {
-#if defined(_MSC_VER) || defined(__cpp_lib_is_swappable)
-// MSVC already implements the C++17 P0185R1 proposal which
-// adds std::is_nothrow_swappable, so use it instead.
+#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;
// Lighter-weight than Conjunction, but evaluates all sub-conditions eagerly.
template <class... Ts>
-using StrictConjunction =
- std::is_same<Bools<Ts::value..., true>, Bools<true, Ts::value...>>;
+struct StrictConjunction
+ : std::is_same<Bools<Ts::value..., true>, Bools<true, Ts::value...>> {};
} // namespace folly
// types) that violate -Wsign-compare and/or -Wbool-compare so suppress them
// in order to not prevent all calling code from using it.
FOLLY_PUSH_WARNING
-FOLLY_GCC_DISABLE_WARNING(sign-compare)
+FOLLY_GCC_DISABLE_WARNING("-Wsign-compare")
#if __GNUC_PREREQ(5, 0)
-FOLLY_GCC_DISABLE_WARNING(bool-compare)
+FOLLY_GCC_DISABLE_WARNING("-Wbool-compare")
#endif
FOLLY_MSVC_DISABLE_WARNING(4388) // sign-compare
FOLLY_MSVC_DISABLE_WARNING(4804) // bool-compare
// Assume nothing when compiling with MSVC.
#ifndef _MSC_VER
-// gcc-5.0 changed string's implementation in libgcc to be non-relocatable
-#if __GNUC__ < 5
+// gcc-5.0 changed string's implementation in libstdc++ to be non-relocatable
+#if !_GLIBCXX_USE_CXX11_ABI
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string)
#endif
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::vector)