Commit e1e39232 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

move FOLLY_DECLVAL to the top of its header

Summary: It is pure syntax - so, dependency-free - and we may like to use in other places in the same header.

Reviewed By: iahs, luciang

Differential Revision: D32946539

fbshipit-source-id: 2843b73af178c6d7636a4431e61017f35a48681e
parent b9e08c66
......@@ -27,6 +27,39 @@
namespace folly {
/*
* FOLLY_DECLVAL(T)
*
* This macro works like std::declval<T>() but does the same thing in a way
* that does not require instantiating a function template.
*
* Use this macro instead of std::declval<T>() in places that are widely
* instantiated to reduce compile-time overhead of instantiating function
* templates.
*
* Note that, like std::declval<T>(), this macro can only be used in
* unevaluated contexts.
*
* There are some small differences between this macro and std::declval<T>().
* - This macro results in a value of type 'T' instead of 'T&&'.
* - This macro requires the type T to be a complete type at the
* point of use.
* If this is a problem then use FOLLY_DECLVAL(T&&) instead, or if T might
* be 'void', then use FOLLY_DECLVAL(std::add_rvalue_reference_t<T>).
*/
#if __cplusplus >= 201703L
#define FOLLY_DECLVAL(...) static_cast<__VA_ARGS__ (*)() noexcept>(nullptr)()
#else
// Don't have noexcept-qualified function types prior to C++17
// so just fall back to a function-template.
namespace detail {
template <typename T>
T declval() noexcept;
} // namespace detail
#define FOLLY_DECLVAL(...) ::folly::detail::declval<__VA_ARGS__>()
#endif
/**
* copy
*
......@@ -419,37 +452,4 @@ struct to_underlying_fn {
};
FOLLY_INLINE_VARIABLE constexpr to_underlying_fn to_underlying;
/*
* FOLLY_DECLVAL(T)
*
* This macro works like std::declval<T>() but does the same thing in a way
* that does not require instantiating a function template.
*
* Use this macro instead of std::declval<T>() in places that are widely
* instantiated to reduce compile-time overhead of instantiating function
* templates.
*
* Note that, like std::declval<T>(), this macro can only be used in
* unevaluated contexts.
*
* There are some small differences between this macro and std::declval<T>().
* - This macro results in a value of type 'T' instead of 'T&&'.
* - This macro requires the type T to be a complete type at the
* point of use.
* If this is a problem then use FOLLY_DECLVAL(T&&) instead, or if T might
* be 'void', then use FOLLY_DECLVAL(std::add_rvalue_reference_t<T>).
*/
#if __cplusplus >= 201703L
#define FOLLY_DECLVAL(...) static_cast<__VA_ARGS__ (*)() noexcept>(nullptr)()
#else
// Don't have noexcept-qualified function types prior to C++17
// so just fall back to a function-template.
namespace detail {
template <typename T>
T declval() noexcept;
} // namespace detail
#define FOLLY_DECLVAL(...) ::folly::detail::declval<__VA_ARGS__>()
#endif
} // namespace folly
......@@ -25,6 +25,13 @@ namespace {
class UtilityTest : public testing::Test {};
} // namespace
// Tests for FOLLY_DECLVAL macro:
static_assert(std::is_same_v<decltype(FOLLY_DECLVAL(int)), int>);
static_assert(std::is_same_v<decltype(FOLLY_DECLVAL(int&)), int&>);
static_assert(std::is_same_v<decltype(FOLLY_DECLVAL(int&&)), int&&>);
static_assert(noexcept(FOLLY_DECLVAL(int)));
TEST_F(UtilityTest, copy) {
struct MyData {};
struct Worker {
......@@ -141,10 +148,3 @@ TEST_F(UtilityTest, to_narrow) {
EXPECT_EQ(100, actual);
}
}
// Tests for FOLLY_DECLVAL macro:
static_assert(std::is_same<decltype(FOLLY_DECLVAL(int)), int>::value);
static_assert(std::is_same<decltype(FOLLY_DECLVAL(int&)), int&>::value);
static_assert(std::is_same<decltype(FOLLY_DECLVAL(int&&)), int&&>::value);
static_assert(noexcept(FOLLY_DECLVAL(int)));
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment