diff options
-rw-r--r-- | CMake/AbseilHelpers.cmake | 16 | ||||
-rw-r--r-- | CMake/AbseilInstallDirs.cmake | 2 | ||||
-rw-r--r-- | CMake/abslConfig.cmake.in | 5 | ||||
-rw-r--r-- | CMakeLists.txt | 28 | ||||
-rw-r--r-- | absl/base/CMakeLists.txt | 11 | ||||
-rw-r--r-- | absl/base/internal/cmake_thread_test.cc | 22 | ||||
-rw-r--r-- | absl/container/inlined_vector.h | 53 | ||||
-rw-r--r-- | absl/container/internal/raw_hash_set_test.cc | 4 | ||||
-rw-r--r-- | absl/copts/AbseilConfigureCopts.cmake | 6 | ||||
-rw-r--r-- | absl/synchronization/CMakeLists.txt | 2 | ||||
-rw-r--r-- | absl/types/BUILD.bazel | 7 | ||||
-rw-r--r-- | absl/types/CMakeLists.txt | 2 | ||||
-rw-r--r-- | absl/types/internal/span.h | 126 | ||||
-rw-r--r-- | absl/types/span.h | 100 |
14 files changed, 235 insertions, 149 deletions
diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index be9a0e9ccf37..58f98c8c3857 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake @@ -59,7 +59,7 @@ set(ABSL_IDE_FOLDER Abseil) # SRCS # "b.cc" # DEPS -# absl_internal_awesome # not "awesome"! +# absl::awesome # not "awesome" ! # PUBLIC # ) # @@ -68,7 +68,7 @@ set(ABSL_IDE_FOLDER Abseil) # main_lib # ... # DEPS -# absl::fantastic_lib # since fantastic_lib is public +# absl::fantastic_lib # ) # # TODO: Implement "ALWAYSLINK" @@ -80,8 +80,12 @@ function(absl_cc_library) ${ARGN} ) - if (NOT ABSL_CC_LIB_TESTONLY OR ABSL_RUN_TESTS) - set(_NAME "${ABSL_CC_LIB_NAME}") + if(NOT ABSL_CC_LIB_TESTONLY OR ABSL_RUN_TESTS) + if(ABSL_ENABLE_INSTALL) + set(_NAME "${ABSL_CC_LIB_NAME}") + else() + set(_NAME "absl_${ABSL_CC_LIB_NAME}") + endif() # Check if this is a header-only library # Note that as of February 2019, many popular OS's (for example, Ubuntu @@ -93,7 +97,7 @@ function(absl_cc_library) list(REMOVE_ITEM ABSL_CC_SRCS "${src_file}") endif() endforeach() - if ("${ABSL_CC_SRCS}" STREQUAL "") + if("${ABSL_CC_SRCS}" STREQUAL "") set(ABSL_CC_LIB_IS_INTERFACE 1) else() set(ABSL_CC_LIB_IS_INTERFACE 0) @@ -155,7 +159,7 @@ function(absl_cc_library) # TODO currently we don't install googletest alongside abseil sources, so # installed abseil can't be tested. - if (NOT ABSL_CC_LIB_TESTONLY) + if(NOT ABSL_CC_LIB_TESTONLY AND ABSL_ENABLE_INSTALL) install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR} LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR} diff --git a/CMake/AbseilInstallDirs.cmake b/CMake/AbseilInstallDirs.cmake index 5b67008bc68c..b67272f830c1 100644 --- a/CMake/AbseilInstallDirs.cmake +++ b/CMake/AbseilInstallDirs.cmake @@ -6,7 +6,7 @@ include(GNUInstallDirs) # Abseil's internal Copybara (https://github.com/google/copybara) workflows and # isn't visible in the CMake buildsystem itself. -if (absl_VERSION) +if(absl_VERSION) set(ABSL_SUBDIR "${PROJECT_NAME}_${PROJECT_VERSION}") set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}/${ABSL_SUBDIR}") set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${ABSL_SUBDIR}") diff --git a/CMake/abslConfig.cmake.in b/CMake/abslConfig.cmake.in index bf8c4f6a0ec9..60847fa7723f 100644 --- a/CMake/abslConfig.cmake.in +++ b/CMake/abslConfig.cmake.in @@ -1,5 +1,6 @@ -## absl CMake configuration file. Note that there is no corresponding -# abslConfigVersion.cmake since non-LTS Abseil isn't versioned. +# absl CMake configuration file. + +include(FindThreads) @PACKAGE_INIT@ diff --git a/CMakeLists.txt b/CMakeLists.txt index ad55fa47c3df..dff46f910da8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,18 +86,6 @@ if(${ABSL_RUN_TESTS}) enable_testing() endif() -# absl:lts-remove-begin(system installation is supported for LTS releases) -# We don't support system-wide installation -list(APPEND SYSTEM_INSTALL_DIRS "/usr/local" "/usr" "/opt/" "/opt/local" "c:/Program Files/${PROJECT_NAME}") -if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX IN_LIST SYSTEM_INSTALL_DIRS) - message(WARNING "\ -The default and system-level install directories are unsupported except in LTS \ -releases of Abseil. Please set CMAKE_INSTALL_PREFIX to install Abseil in your \ -source or build tree directly.\ - ") -endif() -# absl:lts-remove-end - ## check targets if(BUILD_TESTING) @@ -121,7 +109,19 @@ endif() add_subdirectory(absl) -if (ABSL_ENABLE_INSTALL) +if(ABSL_ENABLE_INSTALL) + # absl:lts-remove-begin(system installation is supported for LTS releases) + # We don't support system-wide installation + list(APPEND SYSTEM_INSTALL_DIRS "/usr/local" "/usr" "/opt/" "/opt/local" "c:/Program Files/${PROJECT_NAME}") + if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX IN_LIST SYSTEM_INSTALL_DIRS) + message(WARNING "\ + The default and system-level install directories are unsupported except in LTS \ + releases of Abseil. Please set CMAKE_INSTALL_PREFIX to install Abseil in your \ + source or build tree directly.\ + ") + endif() + # absl:lts-remove-end + # install as a subdirectory only install(EXPORT ${PROJECT_NAME}Targets NAMESPACE absl:: @@ -140,7 +140,7 @@ if (ABSL_ENABLE_INSTALL) # Abseil only has a version in LTS releases. This mechanism is accomplished # Abseil's internal Copybara (https://github.com/google/copybara) workflows and # isn't visible in the CMake buildsystem itself. - if (absl_VERSION) + if(absl_VERSION) write_basic_package_version_file( "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" COMPATIBILITY ExactVersion diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index d8a311c2f1fe..cd1ec4128539 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -88,6 +88,7 @@ absl_cc_library( absl::core_headers absl::dynamic_annotations absl::spinlock_wait + Threads::Threads ) absl_cc_library( @@ -134,6 +135,7 @@ absl_cc_library( absl::core_headers absl::dynamic_annotations absl::spinlock_wait + Threads::Threads PUBLIC ) @@ -438,3 +440,12 @@ absl_cc_test( absl::scoped_set_env gtest_main ) + +absl_cc_test( + NAME + cmake_thread_test + SRCS + "internal/cmake_thread_test.cc" + DEPS + absl::base +) diff --git a/absl/base/internal/cmake_thread_test.cc b/absl/base/internal/cmake_thread_test.cc new file mode 100644 index 000000000000..f70bb24eb7b4 --- /dev/null +++ b/absl/base/internal/cmake_thread_test.cc @@ -0,0 +1,22 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <iostream> +#include "absl/base/internal/thread_identity.h" + +int main() { + auto* tid = absl::base_internal::CurrentThreadIdentityIfPresent(); + // Make sure the above call can't be optimized out + std::cout << (void*)tid << std::endl; +} diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index bd4ed6667ad2..0f066860623c 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -847,7 +847,7 @@ class InlinedVector { private: template <typename H, typename TheT, size_t TheN, typename TheA> - friend auto AbslHashValue(H h, const InlinedVector<TheT, TheN, TheA>& v) -> H; + friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a); const Tag& tag() const { return storage_.allocator_and_tag_.tag(); } @@ -1231,8 +1231,8 @@ class InlinedVector { // Swaps the contents of two inlined vectors. This convenience function // simply calls `InlinedVector::swap()`. template <typename T, size_t N, typename A> -auto swap(InlinedVector<T, N, A>& a, - InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) -> void { +void swap(absl::InlinedVector<T, N, A>& a, + absl::InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) { a.swap(b); } @@ -1240,17 +1240,21 @@ auto swap(InlinedVector<T, N, A>& a, // // Tests the equivalency of the contents of two inlined vectors. template <typename T, size_t N, typename A> -auto operator==(const InlinedVector<T, N, A>& a, - const InlinedVector<T, N, A>& b) -> bool { - return absl::equal(a.begin(), a.end(), b.begin(), b.end()); +bool operator==(const absl::InlinedVector<T, N, A>& a, + const absl::InlinedVector<T, N, A>& b) { + auto a_data = a.data(); + auto a_size = a.size(); + auto b_data = b.data(); + auto b_size = b.size(); + return absl::equal(a_data, a_data + a_size, b_data, b_data + b_size); } // `operator!=()` // // Tests the inequality of the contents of two inlined vectors. template <typename T, size_t N, typename A> -auto operator!=(const InlinedVector<T, N, A>& a, - const InlinedVector<T, N, A>& b) -> bool { +bool operator!=(const absl::InlinedVector<T, N, A>& a, + const absl::InlinedVector<T, N, A>& b) { return !(a == b); } @@ -1259,9 +1263,14 @@ auto operator!=(const InlinedVector<T, N, A>& a, // Tests whether the contents of one inlined vector are less than the contents // of another through a lexicographical comparison operation. template <typename T, size_t N, typename A> -auto operator<(const InlinedVector<T, N, A>& a, const InlinedVector<T, N, A>& b) - -> bool { - return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); +bool operator<(const absl::InlinedVector<T, N, A>& a, + const absl::InlinedVector<T, N, A>& b) { + auto a_data = a.data(); + auto a_size = a.size(); + auto b_data = b.data(); + auto b_size = b.size(); + return std::lexicographical_compare(a_data, a_data + a_size, b_data, + b_data + b_size); } // `operator>()` @@ -1269,8 +1278,8 @@ auto operator<(const InlinedVector<T, N, A>& a, const InlinedVector<T, N, A>& b) // Tests whether the contents of one inlined vector are greater than the // contents of another through a lexicographical comparison operation. template <typename T, size_t N, typename A> -auto operator>(const InlinedVector<T, N, A>& a, const InlinedVector<T, N, A>& b) - -> bool { +bool operator>(const absl::InlinedVector<T, N, A>& a, + const absl::InlinedVector<T, N, A>& b) { return b < a; } @@ -1279,8 +1288,8 @@ auto operator>(const InlinedVector<T, N, A>& a, const InlinedVector<T, N, A>& b) // Tests whether the contents of one inlined vector are less than or equal to // the contents of another through a lexicographical comparison operation. template <typename T, size_t N, typename A> -auto operator<=(const InlinedVector<T, N, A>& a, - const InlinedVector<T, N, A>& b) -> bool { +bool operator<=(const absl::InlinedVector<T, N, A>& a, + const absl::InlinedVector<T, N, A>& b) { return !(b < a); } @@ -1289,8 +1298,8 @@ auto operator<=(const InlinedVector<T, N, A>& a, // Tests whether the contents of one inlined vector are greater than or equal to // the contents of another through a lexicographical comparison operation. template <typename T, size_t N, typename A> -auto operator>=(const InlinedVector<T, N, A>& a, - const InlinedVector<T, N, A>& b) -> bool { +bool operator>=(const absl::InlinedVector<T, N, A>& a, + const absl::InlinedVector<T, N, A>& b) { return !(a < b); } @@ -1299,11 +1308,13 @@ auto operator>=(const InlinedVector<T, N, A>& a, // Provides `absl::Hash` support for inlined vectors. You do not normally call // this function directly. template <typename H, typename TheT, size_t TheN, typename TheA> -auto AbslHashValue(H h, const InlinedVector<TheT, TheN, TheA>& v) -> H { - auto p = v.data(); - auto n = v.size(); - return H::combine(H::combine_contiguous(std::move(h), p, n), n); +H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a) { + auto a_data = a.data(); + auto a_size = a.size(); + return H::combine(H::combine_contiguous(std::move(h), a_data, a_size), + a_size); } + } // namespace absl #endif // ABSL_CONTAINER_INLINED_VECTOR_H_ diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index 4d94f7853219..7d96ed90be9c 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -414,10 +414,10 @@ TEST(Table, Prefetch) { t.prefetch(2); // Do not run in debug mode, when prefetch is not implemented, or when - // sanitizers are enabled. + // sanitizers are enabled, or on WebAssembly. #if defined(NDEBUG) && defined(__GNUC__) && !defined(ADDRESS_SANITIZER) && \ !defined(MEMORY_SANITIZER) && !defined(THREAD_SANITIZER) && \ - !defined(UNDEFINED_BEHAVIOR_SANITIZER) + !defined(UNDEFINED_BEHAVIOR_SANITIZER) && !defined(__EMSCRIPTEN__) const auto now = [] { return absl::base_internal::CycleClock::Now(); }; // Make size enough to not fit in L2 cache (16.7 Mb) diff --git a/absl/copts/AbseilConfigureCopts.cmake b/absl/copts/AbseilConfigureCopts.cmake index b2b3f88d5055..ae29d9e9a045 100644 --- a/absl/copts/AbseilConfigureCopts.cmake +++ b/absl/copts/AbseilConfigureCopts.cmake @@ -5,13 +5,13 @@ set(ABSL_LSAN_LINKOPTS "") set(ABSL_HAVE_LSAN OFF) set(ABSL_DEFAULT_LINKOPTS "") -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(ABSL_DEFAULT_COPTS "${ABSL_GCC_FLAGS}") set(ABSL_TEST_COPTS "${ABSL_GCC_FLAGS};${ABSL_GCC_TEST_FLAGS}") set(ABSL_EXCEPTIONS_FLAG "${ABSL_GCC_EXCEPTIONS_FLAGS}") elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # MATCHES so we get both Clang and AppleClang - if (MSVC) + if(MSVC) # clang-cl is half MSVC, half LLVM set(ABSL_DEFAULT_COPTS "${ABSL_CLANG_CL_FLAGS}") set(ABSL_TEST_COPTS "${ABSL_CLANG_CL_FLAGS};${ABSL_CLANG_CL_TEST_FLAGS}") @@ -21,7 +21,7 @@ elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(ABSL_TEST_COPTS "${ABSL_LLVM_FLAGS};${ABSL_LLVM_TEST_FLAGS}") set(ABSL_EXCEPTIONS_FLAG "${ABSL_LLVM_EXCEPTIONS_FLAGS}") set(ABSL_DEFAULT_LINKOPTS "${ABSL_MSVC_LINKOPTS}") - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # AppleClang doesn't have lsan # https://developer.apple.com/documentation/code_diagnostics if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 3.5) diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt index 68473b735d34..9156f5ad1cd1 100644 --- a/absl/synchronization/CMakeLists.txt +++ b/absl/synchronization/CMakeLists.txt @@ -64,6 +64,7 @@ absl_cc_library( absl::stacktrace absl::symbolize absl::time + Threads::Threads PUBLIC ) @@ -191,5 +192,4 @@ absl_cc_test( absl::synchronization absl::base absl::core_headers - Threads::Threads ) diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index a62522e469dd..feac34b1c9f9 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel @@ -117,7 +117,12 @@ cc_test( cc_library( name = "span", - hdrs = ["span.h"], + srcs = [ + "internal/span.h", + ], + hdrs = [ + "span.h", + ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt index 910c099a94ab..56f9fffd6f92 100644 --- a/absl/types/CMakeLists.txt +++ b/absl/types/CMakeLists.txt @@ -114,6 +114,8 @@ absl_cc_library( span HDRS "span.h" + SRCS + "internal/span.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS diff --git a/absl/types/internal/span.h b/absl/types/internal/span.h new file mode 100644 index 000000000000..d203aad59165 --- /dev/null +++ b/absl/types/internal/span.h @@ -0,0 +1,126 @@ +// +// Copyright 2019 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef ABSL_TYPES_INTERNAL_SPAN_H_ +#define ABSL_TYPES_INTERNAL_SPAN_H_ + +#include <algorithm> +#include <cstddef> +#include <string> +#include <type_traits> + +#include "absl/algorithm/algorithm.h" +#include "absl/base/internal/throw_delegate.h" +#include "absl/meta/type_traits.h" + +namespace absl { + +namespace span_internal { +// A constexpr min function +constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; } + +// Wrappers for access to container data pointers. +template <typename C> +constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references) + -> decltype(c.data()) { + return c.data(); +} + +// Before C++17, std::string::data returns a const char* in all cases. +inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references) + int) noexcept { + return &s[0]; +} + +template <typename C> +constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references) + -> decltype(GetDataImpl(c, 0)) { + return GetDataImpl(c, 0); +} + +// Detection idioms for size() and data(). +template <typename C> +using HasSize = + std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>; + +// We want to enable conversion from vector<T*> to Span<const T* const> but +// disable conversion from vector<Derived> to Span<Base>. Here we use +// the fact that U** is convertible to Q* const* if and only if Q is the same +// type or a more cv-qualified version of U. We also decay the result type of +// data() to avoid problems with classes which have a member function data() +// which returns a reference. +template <typename T, typename C> +using HasData = + std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*, + T* const*>; + +// Extracts value type from a Container +template <typename C> +struct ElementType { + using type = typename absl::remove_reference_t<C>::value_type; +}; + +template <typename T, size_t N> +struct ElementType<T (&)[N]> { + using type = T; +}; + +template <typename C> +using ElementT = typename ElementType<C>::type; + +template <typename T> +using EnableIfMutable = + typename std::enable_if<!std::is_const<T>::value, int>::type; + +template <template <typename> class SpanT, typename T> +bool EqualImpl(SpanT<T> a, SpanT<T> b) { + static_assert(std::is_const<T>::value, ""); + return absl::equal(a.begin(), a.end(), b.begin(), b.end()); +} + +template <template <typename> class SpanT, typename T> +bool LessThanImpl(SpanT<T> a, SpanT<T> b) { + // We can't use value_type since that is remove_cv_t<T>, so we go the long way + // around. + static_assert(std::is_const<T>::value, ""); + return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); +} + +// The `IsConvertible` classes here are needed because of the +// `std::is_convertible` bug in libcxx when compiled with GCC. This build +// configuration is used by Android NDK toolchain. Reference link: +// https://bugs.llvm.org/show_bug.cgi?id=27538. +template <typename From, typename To> +struct IsConvertibleHelper { + private: + static std::true_type testval(To); + static std::false_type testval(...); + + public: + using type = decltype(testval(std::declval<From>())); +}; + +template <typename From, typename To> +struct IsConvertible : IsConvertibleHelper<From, To>::type {}; + +// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the +// older version of libcxx is not supported. +template <typename From, typename To> +using EnableIfConvertibleTo = + typename std::enable_if<IsConvertible<From, To>::value>::type; +} // namespace span_internal +} // namespace absl + +#endif // ABSL_TYPES_INTERNAL_SPAN_H_ diff --git a/absl/types/span.h b/absl/types/span.h index e5c4fe1e4dc2..b007fc1fd3df 100644 --- a/absl/types/span.h +++ b/absl/types/span.h @@ -60,114 +60,18 @@ #include <cstddef> #include <initializer_list> #include <iterator> -#include <string> #include <type_traits> #include <utility> -#include "absl/algorithm/algorithm.h" #include "absl/base/internal/throw_delegate.h" #include "absl/base/macros.h" #include "absl/base/optimization.h" -#include "absl/base/port.h" +#include "absl/base/port.h" // TODO(strel): remove this include #include "absl/meta/type_traits.h" +#include "absl/types/internal/span.h" namespace absl { -namespace span_internal { -// A constexpr min function -constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; } - -// Wrappers for access to container data pointers. -template <typename C> -constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references) - -> decltype(c.data()) { - return c.data(); -} - -// Before C++17, std::string::data returns a const char* in all cases. -inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references) - int) noexcept { - return &s[0]; -} - -template <typename C> -constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references) - -> decltype(GetDataImpl(c, 0)) { - return GetDataImpl(c, 0); -} - -// Detection idioms for size() and data(). -template <typename C> -using HasSize = - std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>; - -// We want to enable conversion from vector<T*> to Span<const T* const> but -// disable conversion from vector<Derived> to Span<Base>. Here we use -// the fact that U** is convertible to Q* const* if and only if Q is the same -// type or a more cv-qualified version of U. We also decay the result type of -// data() to avoid problems with classes which have a member function data() -// which returns a reference. -template <typename T, typename C> -using HasData = - std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*, - T* const*>; - -// Extracts value type from a Container -template <typename C> -struct ElementType { - using type = typename absl::remove_reference_t<C>::value_type; -}; - -template <typename T, size_t N> -struct ElementType<T (&)[N]> { - using type = T; -}; - -template <typename C> -using ElementT = typename ElementType<C>::type; - -template <typename T> -using EnableIfMutable = - typename std::enable_if<!std::is_const<T>::value, int>::type; - -template <template <typename> class SpanT, typename T> -bool EqualImpl(SpanT<T> a, SpanT<T> b) { - static_assert(std::is_const<T>::value, ""); - return absl::equal(a.begin(), a.end(), b.begin(), b.end()); -} - -template <template <typename> class SpanT, typename T> -bool LessThanImpl(SpanT<T> a, SpanT<T> b) { - // We can't use value_type since that is remove_cv_t<T>, so we go the long way - // around. - static_assert(std::is_const<T>::value, ""); - return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); -} - -// The `IsConvertible` classes here are needed because of the -// `std::is_convertible` bug in libcxx when compiled with GCC. This build -// configuration is used by Android NDK toolchain. Reference link: -// https://bugs.llvm.org/show_bug.cgi?id=27538. -template <typename From, typename To> -struct IsConvertibleHelper { - private: - static std::true_type testval(To); - static std::false_type testval(...); - - public: - using type = decltype(testval(std::declval<From>())); -}; - -template <typename From, typename To> -struct IsConvertible : IsConvertibleHelper<From, To>::type {}; - -// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the -// older version of libcxx is not supported. -template <typename From, typename To> -using EnableIfConvertibleTo = - typename std::enable_if<IsConvertible<From, To>::value>::type; -} // namespace span_internal - //------------------------------------------------------------------------------ // Span //------------------------------------------------------------------------------ |