Index: base/template_util.h |
diff --git a/base/template_util.h b/base/template_util.h |
index 536cad8f3a3b6f0d77dc7d28076753470d2e90bc..282db6d50caf53416dd92e534acee3a1cb5cb5e6 100644 |
--- a/base/template_util.h |
+++ b/base/template_util.h |
@@ -36,20 +36,82 @@ |
namespace base { |
+// C++14 --------------------------------------------------------------------- |
danakj
2017/06/23 21:10:26
I would honestly prefer to not add things here whe
brettw
2017/06/23 21:19:45
I think all this is needed is for TransparentCompa
vmpstr
2017/06/23 21:45:14
I agree. I'd rather not start adding things from C
dyaroshev
2017/06/26 11:47:29
This is why we can't have nice things)
Ok, I foun
vmpstr
2017/06/26 15:35:53
Indeed
|
+// These can be replaced with the ones from the standard once we have C++14. |
+ |
+// std::enable_if_t: http://en.cppreference.com/w/cpp/types/enable_if |
+template <bool condition, typename T = void> |
+using enable_if_t = typename std::enable_if<condition, T>::type; |
+ |
+// std::conditional_t: http://en.cppreference.com/w/cpp/types/conditional |
+template <bool condition, typename T, typename U> |
+using conditional_t = typename std::conditional<condition, T, U>::type; |
+ |
+// C++17 ---------------------------------------------------------------------- |
+// These can be replaced with the ones from the standard once we have C++17. |
vmpstr
2017/06/23 21:45:14
I'll admit I'm not too familiar with the detection
dyaroshev
2017/06/26 11:47:29
Done.
|
+ |
+// std::void_t: http://en.cppreference.com/w/cpp/types/void_t |
+// Needed for the detection idiom. |
+template <typename...> |
+using void_t = void; |
+ |
+// std::nonesuch: http://en.cppreference.com/w/cpp/experimental/nonesuch |
+// Needed for the detection idiom. |
+struct nonesuch { |
+ nonesuch() = delete; |
+ ~nonesuch() = delete; |
+ nonesuch(nonesuch const&) = delete; |
+ void operator=(nonesuch const&) = delete; |
+}; |
+ |
+// Implementation of the detection idiom from cppreference: |
+// http://en.cppreference.com/w/cpp/experimental/is_detected |
+namespace internal { |
+ |
+template <typename Default, |
+ typename AlwaysVoid, |
+ template <typename...> class Op, |
+ typename... Args> |
+struct detector { |
+ using value_t = std::false_type; |
+ using type = Default; |
+}; |
+ |
+template <typename Default, template <typename...> class Op, typename... Args> |
+struct detector<Default, void_t<Op<Args...>>, Op, Args...> { |
+ using value_t = std::true_type; |
+ using type = Op<Args...>; |
+}; |
+ |
+} // namespace internal |
+ |
+// std::is_detected: http://en.cppreference.com/w/cpp/experimental/is_detected |
+template <template <typename...> class Op, typename... Args> |
+using is_detected = |
+ typename internal::detector<nonesuch, void, Op, Args...>::value_t; |
vmpstr
2017/06/23 21:45:14
AFAICT, we're not using detector::type, just the v
dyaroshev
2017/06/26 11:47:29
Removed altogether.
|
+ |
+// std::is_detected_v, implemented as a constexpr function instead of a variable |
+// template, since we don't have those. |
+// http://en.cppreference.com/w/cpp/experimental/is_detected |
+template <template <typename...> class Op, typename... Args> |
+constexpr bool is_detected_c() { |
+ return is_detected<Op, Args...>::value; |
vmpstr
2017/06/23 21:45:14
Can you comment that ::value is on std::true_type/
dyaroshev
2017/06/26 11:47:29
Not applicable.
|
+} |
+ |
+// ---------------------------------------------------------------------------- |
+ |
template <class T> struct is_non_const_reference : std::false_type {}; |
template <class T> struct is_non_const_reference<T&> : std::true_type {}; |
template <class T> struct is_non_const_reference<const T&> : std::false_type {}; |
namespace internal { |
-// Uses expression SFINAE to detect whether using operator<< would work. |
-template <typename T, typename = void> |
-struct SupportsOstreamOperator : std::false_type {}; |
template <typename T> |
-struct SupportsOstreamOperator<T, |
- decltype(void(std::declval<std::ostream&>() |
- << std::declval<T>()))> |
- : std::true_type {}; |
+using HasOstreamOperator = |
+ decltype(std::declval<std::ostream&>() << std::declval<T>()); |
+ |
+template <typename T> |
+using SupportsOstreamOperator = base::is_detected<HasOstreamOperator, T>; |
} // namespace internal |