X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FTraits.h;h=2b94df1360effe21828adedb51b864e7d2282116;hb=fd915b73606e09a5f46a1bca0a5d3643a1567014;hp=bc0a0bf68847f1270b389eb9a87d5a6b3ce2088e;hpb=1bf1654c689b31ac7b53f499b8f1810548fbda7a;p=folly.git diff --git a/folly/Traits.h b/folly/Traits.h index bc0a0bf6..2b94df13 100644 --- a/folly/Traits.h +++ b/folly/Traits.h @@ -1,5 +1,5 @@ /* - * Copyright 2013 Facebook, Inc. + * Copyright 2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +20,22 @@ #define FOLLY_BASE_TRAITS_H_ #include +#include #include - +#include + +#include + +// libc++ doesn't provide this header, nor does msvc +#ifdef FOLLY_HAVE_BITS_CXXCONFIG_H +// This file appears in two locations: inside fbcode and in the +// libstdc++ source code (when embedding fbstring as std::string). +// To aid in this schizophrenic use, two macros are defined in +// c++config.h: +// _LIBSTDCXX_FBSTRING - Set inside libstdc++. This is useful to +// gate use inside fbcode v. libstdc++ #include +#endif #include #include @@ -222,7 +235,7 @@ template struct IsZeroInitializable * although that is not guaranteed by the standard. */ -namespace std { +FOLLY_NAMESPACE_STD_BEGIN template struct pair; @@ -246,7 +259,7 @@ template template class shared_ptr; -} +FOLLY_NAMESPACE_STD_END namespace boost { @@ -277,10 +290,42 @@ struct IsOneOf { enum { value = std::is_same::value || IsOneOf::value }; }; +/** + * A traits class to check for incomplete types. + * + * Example: + * + * struct FullyDeclared {}; // complete type + * struct ForwardDeclared; // incomplete type + * + * is_complete::value // evaluates to true + * is_complete::value // evaluates to true + * is_complete::value // evaluates to false + * + * struct ForwardDeclared {}; // declared, at last + * + * is_complete::value // now it evaluates to true + * + * @author: Marcelo Juchem + */ +template +class is_complete { + template struct sfinae {}; + template + constexpr static bool test(sfinae*) { return true; } + template constexpr static bool test(...) { return false; } +public: + constexpr static bool value = test(nullptr); +}; + /* - * Complementary type traits to check for a negative/non-positive value. + * Complementary type traits for integral comparisons. + * + * For instance, `if(x < 0)` yields an error in clang for unsigned types + * when -Werror is used due to -Wtautological-compare * - * `if(x < 0)` yields an error in clang for unsigned types when -Werror is used + * + * @author: Marcelo Juchem */ namespace detail { @@ -295,6 +340,68 @@ struct is_negative_impl { constexpr static bool check(T x) { return false; } }; +template +bool less_than_impl( + typename std::enable_if< + (rhs <= std::numeric_limits::max() + && rhs > std::numeric_limits::min()), + LHS + >::type const lhs +) { + return lhs < rhs; +} + +template +bool less_than_impl( + typename std::enable_if< + (rhs > std::numeric_limits::max()), + LHS + >::type const +) { + return true; +} + +template +bool less_than_impl( + typename std::enable_if< + (rhs <= std::numeric_limits::min()), + LHS + >::type const +) { + return false; +} + +template +bool greater_than_impl( + typename std::enable_if< + (rhs <= std::numeric_limits::max() + && rhs >= std::numeric_limits::min()), + LHS + >::type const lhs +) { + return lhs > rhs; +} + +template +bool greater_than_impl( + typename std::enable_if< + (rhs > std::numeric_limits::max()), + LHS + >::type const +) { + return false; +} + +template +bool greater_than_impl( + typename std::enable_if< + (rhs < std::numeric_limits::min()), + LHS + >::type const +) { + return true; +} + } // namespace detail { // same as `x < 0` @@ -307,14 +414,36 @@ constexpr bool is_negative(T x) { template constexpr bool is_non_positive(T x) { return !x || folly::is_negative(x); } +// same as `x > 0` +template +constexpr bool is_positive(T x) { return !is_non_positive(x); } + +// same as `x >= 0` +template +constexpr bool is_non_negative(T x) { + return !x || is_positive(x); +} + +template +bool less_than(LHS const lhs) { + return detail::less_than_impl< + RHS, rhs, typename std::remove_reference::type + >(lhs); +} + +template +bool greater_than(LHS const lhs) { + return detail::greater_than_impl< + RHS, rhs, typename std::remove_reference::type + >(lhs); +} + } // namespace folly FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::vector); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::list); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::deque); -FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(std::map); -FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::set); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::unique_ptr); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(std::shared_ptr); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(std::function); @@ -382,6 +511,8 @@ FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(boost::shared_ptr); * cout << "Does class Bar have a member double test(const string&, long)? " * << boolalpha << has_test_traits::value; * } + * + * @author: Marcelo Juchem */ #define FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(classname, func_name) \ template class classname; \