Commit e3974815 authored by Eric Niebler's avatar Eric Niebler Committed by Facebook Github Bot

add folly::void_t like C++17's std::void_t

Summary:
C++17 is adding std::void_t. It's handy for controlling class template partial specialization. Folly should have it too.

See http://en.cppreference.com/w/cpp/types/void_t

Reviewed By: yfeldblum

Differential Revision: D4387302

fbshipit-source-id: 85f955f3d8cfacbd6c9e61fb3f5cf53c056459bb
parent c5e6d87b
...@@ -149,6 +149,41 @@ namespace folly { ...@@ -149,6 +149,41 @@ namespace folly {
template <typename T> template <typename T>
using _t = typename T::type; 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 * IsRelocatable<T>::value describes the ability of moving around
* memory a value of type T by using memcpy (as opposed to the * memory a value of type T by using memcpy (as opposed to the
......
...@@ -216,3 +216,23 @@ TEST(Traits, actuallyRelocatable) { ...@@ -216,3 +216,23 @@ TEST(Traits, actuallyRelocatable) {
testIsRelocatable<std::vector<char>>(5, 'g'); testIsRelocatable<std::vector<char>>(5, 'g');
} }
namespace {
// 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 {};
}
TEST(Traits, void_t) {
EXPECT_TRUE((::std::is_same<folly::void_t<>, void>::value));
EXPECT_TRUE((::std::is_same<folly::void_t<int>, void>::value));
EXPECT_TRUE((::std::is_same<folly::void_t<int, short>, void>::value));
EXPECT_TRUE(
(::std::is_same<folly::void_t<int, short, std::string>, void>::value));
EXPECT_TRUE((::has_value_type<std::string>::value));
EXPECT_FALSE((::has_value_type<int>::value));
}
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