X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FTraits.h;h=fb797f377bb72a7f860180c8ea511066c15ce0c5;hp=eed02dc620a37e0bce2fdb123e570550196c9a56;hb=7fc3f9174951941df7a7a32acf320185716c26a6;hpb=160f868c3f824c2abcb11a80d6c3b27a162f3710 diff --git a/folly/Traits.h b/folly/Traits.h index eed02dc6..fb797f37 100644 --- a/folly/Traits.h +++ b/folly/Traits.h @@ -156,10 +156,26 @@ template using _t = typename T::type; /** + * type_t + * + * A type alias for the first template type argument. `type_t` is useful for + * controlling class-template and function-template partial specialization. + * + * Example: + * + * template + * class Container { + * public: + * template + * Container( + * type_t()...))>, + * Args&&...); + * }; + * * void_t * * A type alias for `void`. `void_t` is useful for controling class-template - * partial specialization. + * and function-template partial specialization. * * Example: * @@ -172,23 +188,48 @@ using _t = typename T::type; * struct has_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) +/** + * There is a bug in libstdc++, libc++, and MSVC's STL that causes it to + * ignore unused template parameter arguments in template aliases and does not + * cause substitution failures. This defect has been recorded here: + * http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558. + * + * This causes the implementation of std::void_t to be buggy, as it is likely + * defined as something like the following: + * + * template + * using void_t = void; + * + * This causes the compiler to ignore all the template arguments and does not + * help when one wants to cause substitution failures. Rather declarations + * which have void_t in orthogonal specializations are treated as the same. + * For example, assuming the possible `T` types are only allowed to have + * either the alias `one` or `two` and never both or none: + * + * template ::one>* = nullptr> + * void foo(T&&) {} + * template ::two>* = nullptr> + * void foo(T&&) {} + * + * The second foo() will be a redefinition because it conflicts with the first + * one; void_t does not cause substitution failures - the template types are + * just ignored. + */ namespace traits_detail { -template -struct void_t_ { - using type = void; +template +struct type_t_ { + using type = T; }; } // namespace traits_detail +template +using type_t = typename traits_detail::type_t_::type; template -using void_t = _t>; - -#endif // defined(__cpp_lib_void_t) || defined(_MSC_VER) +using void_t = type_t; /** * IsRelocatable::value describes the ability of moving around @@ -267,11 +308,12 @@ struct is_trivially_copyable : std::is_trivial {}; template using is_trivially_copyable = std::is_trivially_copyable; #endif -} +} // namespace traits_detail struct Ignore { + Ignore() = default; template - /* implicit */ Ignore(const T&) {} + constexpr /* implicit */ Ignore(const T&) {} template const Ignore& operator=(T const&) const { return *this; } }; @@ -288,7 +330,7 @@ struct IsEqualityComparable decltype(std::declval() == std::declval()), bool > {}; -} +} // namespace traits_detail_IsEqualityComparable /* using override */ using traits_detail_IsEqualityComparable:: IsEqualityComparable; @@ -302,7 +344,7 @@ struct IsLessThanComparable decltype(std::declval() < std::declval()), bool > {}; -} +} // namespace traits_detail_IsLessThanComparable /* using override */ using traits_detail_IsLessThanComparable:: IsLessThanComparable; @@ -330,7 +372,7 @@ struct IsNothrowSwappable noexcept(swap(std::declval(), std::declval())) > {}; #endif -} +} // namespace traits_detail_IsNothrowSwappable /* using override */ using traits_detail_IsNothrowSwappable::IsNothrowSwappable; @@ -386,11 +428,11 @@ struct Bools { // Lighter-weight than Conjunction, but evaluates all sub-conditions eagerly. template -struct StrictConjunction - : std::is_same, Bools<(Ts::value || true)...>> {}; +struct StrictConjunction + : std::is_same, Bools<(Ts::value || true)...>> {}; template -struct StrictDisjunction +struct StrictDisjunction : Negation< std::is_same, Bools<(Ts::value && false)...>> > {}; @@ -402,12 +444,12 @@ struct StrictDisjunction * regular type, use it like this: * * // Make sure you're at namespace ::folly scope - * template<> FOLLY_ASSUME_RELOCATABLE(MyType) + * template <> FOLLY_ASSUME_RELOCATABLE(MyType) * * When using it with a template type, use it like this: * * // Make sure you're at namespace ::folly scope - * template + * template * FOLLY_ASSUME_RELOCATABLE(MyType) */ #define FOLLY_ASSUME_RELOCATABLE(...) \ @@ -570,7 +612,7 @@ bool greater_than_impl(LHS const lhs) { FOLLY_POP_WARNING -} // namespace detail { +} // namespace detail // same as `x < 0` template