blob: 4f004cda8bec363069fab09f18fc209bd929fba6 [file] [log] [blame]
kwibergd3134032016-09-05 07:46:20 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef RTC_BASE_TYPE_TRAITS_H_
12#define RTC_BASE_TYPE_TRAITS_H_
kwibergd3134032016-09-05 07:46:20 -070013
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020014#include <cstddef>
15#include <type_traits>
kwibergd3134032016-09-05 07:46:20 -070016
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020017namespace 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.
21template <typename DS, typename T>
22class 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
39namespace test_has_data_and_size {
40
41template <typename DR, typename SR>
42struct Test1 {
43 DR data();
44 SR size();
45};
46static_assert(HasDataAndSize<Test1<int*, int>, int>::value, "");
47static_assert(HasDataAndSize<Test1<int*, int>, const int>::value, "");
48static_assert(HasDataAndSize<Test1<const int*, int>, const int>::value, "");
49static_assert(!HasDataAndSize<Test1<const int*, int>, int>::value,
50 "implicit cast of const int* to int*");
51static_assert(!HasDataAndSize<Test1<char*, size_t>, int>::value,
52 "implicit cast of char* to int*");
53
54struct Test2 {
55 int* data;
56 size_t size;
57};
58static_assert(!HasDataAndSize<Test2, int>::value,
59 ".data and .size aren't functions");
60
61struct Test3 {
62 int* data();
63};
64static_assert(!HasDataAndSize<Test3, int>::value, ".size() is missing");
65
66class Test4 {
67 int* data();
68 size_t size();
69};
70static_assert(!HasDataAndSize<Test4, int>::value,
71 ".data() and .size() are private");
72
73} // namespace test_has_data_and_size
74
75namespace type_traits_impl {
76
77// Determines if the given type is an enum that converts implicitly to
78// an integral type.
79template <typename T>
80struct 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.
105template <typename T>
106struct 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
115namespace test_enum_intlike {
116
117enum E1 { e1 };
118enum { e2 };
119enum class E3 { e3 };
120struct S {};
121
122static_assert(type_traits_impl::IsIntEnum<E1>::value, "");
123static_assert(type_traits_impl::IsIntEnum<decltype(e2)>::value, "");
124static_assert(!type_traits_impl::IsIntEnum<E3>::value, "");
125static_assert(!type_traits_impl::IsIntEnum<int>::value, "");
126static_assert(!type_traits_impl::IsIntEnum<float>::value, "");
127static_assert(!type_traits_impl::IsIntEnum<S>::value, "");
128
129static_assert(IsIntlike<E1>::value, "");
130static_assert(IsIntlike<decltype(e2)>::value, "");
131static_assert(!IsIntlike<E3>::value, "");
132static_assert(IsIntlike<int>::value, "");
133static_assert(!IsIntlike<float>::value, "");
134static_assert(!IsIntlike<S>::value, "");
135
136} // test_enum_intlike
137
138} // namespace rtc
kwibergd3134032016-09-05 07:46:20 -0700139
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200140#endif // RTC_BASE_TYPE_TRAITS_H_