1 /* 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef RTC_BASE_TYPE_TRAITS_H_ 12 #define RTC_BASE_TYPE_TRAITS_H_ 13 14 #include <cstddef> 15 #include <type_traits> 16 17 namespace rtc { 18 19 // Determines if the given class has zero-argument .data() and .size() methods 20 // whose return values are convertible to T* and size_t, respectively. 21 template <typename DS, typename T> 22 class HasDataAndSize { 23 private: 24 template < 25 typename C, 26 typename std::enable_if< 27 std::is_convertible<decltype(std::declval<C>().data()), T*>::value && 28 std::is_convertible<decltype(std::declval<C>().size()), 29 std::size_t>::value>::type* = nullptr> 30 static int Test(int); 31 32 template <typename> 33 static char Test(...); 34 35 public: 36 static constexpr bool value = std::is_same<decltype(Test<DS>(0)), int>::value; 37 }; 38 39 namespace test_has_data_and_size { 40 41 template <typename DR, typename SR> 42 struct Test1 { 43 DR data(); 44 SR size(); 45 }; 46 static_assert(HasDataAndSize<Test1<int*, int>, int>::value, ""); 47 static_assert(HasDataAndSize<Test1<int*, int>, const int>::value, ""); 48 static_assert(HasDataAndSize<Test1<const int*, int>, const int>::value, ""); 49 static_assert(!HasDataAndSize<Test1<const int*, int>, int>::value, 50 "implicit cast of const int* to int*"); 51 static_assert(!HasDataAndSize<Test1<char*, size_t>, int>::value, 52 "implicit cast of char* to int*"); 53 54 struct Test2 { 55 int* data; 56 size_t size; 57 }; 58 static_assert(!HasDataAndSize<Test2, int>::value, 59 ".data and .size aren't functions"); 60 61 struct Test3 { 62 int* data(); 63 }; 64 static_assert(!HasDataAndSize<Test3, int>::value, ".size() is missing"); 65 66 class Test4 { 67 int* data(); 68 size_t size(); 69 }; 70 static_assert(!HasDataAndSize<Test4, int>::value, 71 ".data() and .size() are private"); 72 73 } // namespace test_has_data_and_size 74 75 namespace type_traits_impl { 76 77 // Determines if the given type is an enum that converts implicitly to 78 // an integral type. 79 template <typename T> 80 struct IsIntEnum { 81 private: 82 // This overload is used if the type is an enum, and unary plus 83 // compiles and turns it into an integral type. 84 template <typename X, 85 typename std::enable_if< 86 std::is_enum<X>::value && 87 std::is_integral<decltype(+std::declval<X>())>::value>::type* = 88 nullptr> 89 static int Test(int); 90 91 // Otherwise, this overload is used. 92 template <typename> 93 static char Test(...); 94 95 public: 96 static constexpr bool value = 97 std::is_same<decltype(Test<typename std::remove_reference<T>::type>(0)), 98 int>::value; 99 }; 100 101 } // namespace type_traits_impl 102 103 // Determines if the given type is integral, or an enum that 104 // converts implicitly to an integral type. 105 template <typename T> 106 struct IsIntlike { 107 private: 108 using X = typename std::remove_reference<T>::type; 109 110 public: 111 static constexpr bool value = 112 std::is_integral<X>::value || type_traits_impl::IsIntEnum<X>::value; 113 }; 114 115 namespace test_enum_intlike { 116 117 enum E1 { e1 }; 118 enum { e2 }; 119 enum class E3 { e3 }; 120 struct S {}; 121 122 static_assert(type_traits_impl::IsIntEnum<E1>::value, ""); 123 static_assert(type_traits_impl::IsIntEnum<decltype(e2)>::value, ""); 124 static_assert(!type_traits_impl::IsIntEnum<E3>::value, ""); 125 static_assert(!type_traits_impl::IsIntEnum<int>::value, ""); 126 static_assert(!type_traits_impl::IsIntEnum<float>::value, ""); 127 static_assert(!type_traits_impl::IsIntEnum<S>::value, ""); 128 129 static_assert(IsIntlike<E1>::value, ""); 130 static_assert(IsIntlike<decltype(e2)>::value, ""); 131 static_assert(!IsIntlike<E3>::value, ""); 132 static_assert(IsIntlike<int>::value, ""); 133 static_assert(!IsIntlike<float>::value, ""); 134 static_assert(!IsIntlike<S>::value, ""); 135 136 } // namespace test_enum_intlike 137 138 } // namespace rtc 139 140 #endif // RTC_BASE_TYPE_TRAITS_H_ 141