X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FTraits.h;h=fb797f377bb72a7f860180c8ea511066c15ce0c5;hb=36ac103264634cafe2944c33a9677ce9a8b2ac2d;hp=20e2de91f2024c18caf1210e3a1960390eb26c8b;hpb=d4aacd244f21e76dce685365acc281a9015897c1;p=folly.git diff --git a/folly/Traits.h b/folly/Traits.h index 20e2de91..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)...>> > {};