/* * Copyright 2016 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef RTC_BASE_TYPE_TRAITS_H_ #define RTC_BASE_TYPE_TRAITS_H_ #include #include namespace rtc { // Determines if the given class has zero-argument .data() and .size() methods // whose return values are convertible to T* and size_t, respectively. template class HasDataAndSize { private: template < typename C, typename std::enable_if< std::is_convertible().data()), T*>::value && std::is_convertible().size()), std::size_t>::value>::type* = nullptr> static int Test(int); template static char Test(...); public: static constexpr bool value = std::is_same(0)), int>::value; }; namespace test_has_data_and_size { template struct Test1 { DR data(); SR size(); }; static_assert(HasDataAndSize, int>::value, ""); static_assert(HasDataAndSize, const int>::value, ""); static_assert(HasDataAndSize, const int>::value, ""); static_assert(!HasDataAndSize, int>::value, "implicit cast of const int* to int*"); static_assert(!HasDataAndSize, int>::value, "implicit cast of char* to int*"); struct Test2 { int* data; size_t size; }; static_assert(!HasDataAndSize::value, ".data and .size aren't functions"); struct Test3 { int* data(); }; static_assert(!HasDataAndSize::value, ".size() is missing"); class Test4 { int* data(); size_t size(); }; static_assert(!HasDataAndSize::value, ".data() and .size() are private"); } // namespace test_has_data_and_size namespace type_traits_impl { // Determines if the given type is an enum that converts implicitly to // an integral type. template struct IsIntEnum { private: // This overload is used if the type is an enum, and unary plus // compiles and turns it into an integral type. template ::value && std::is_integral())>::value>::type* = nullptr> static int Test(int); // Otherwise, this overload is used. template static char Test(...); public: static constexpr bool value = std::is_same::type>(0)), int>::value; }; } // namespace type_traits_impl // Determines if the given type is integral, or an enum that // converts implicitly to an integral type. template struct IsIntlike { private: using X = typename std::remove_reference::type; public: static constexpr bool value = std::is_integral::value || type_traits_impl::IsIntEnum::value; }; namespace test_enum_intlike { enum E1 { e1 }; enum { e2 }; enum class E3 { e3 }; struct S {}; static_assert(type_traits_impl::IsIntEnum::value, ""); static_assert(type_traits_impl::IsIntEnum::value, ""); static_assert(!type_traits_impl::IsIntEnum::value, ""); static_assert(!type_traits_impl::IsIntEnum::value, ""); static_assert(!type_traits_impl::IsIntEnum::value, ""); static_assert(!type_traits_impl::IsIntEnum::value, ""); static_assert(IsIntlike::value, ""); static_assert(IsIntlike::value, ""); static_assert(!IsIntlike::value, ""); static_assert(IsIntlike::value, ""); static_assert(!IsIntlike::value, ""); static_assert(!IsIntlike::value, ""); } // namespace test_enum_intlike } // namespace rtc #endif // RTC_BASE_TYPE_TRAITS_H_