pax_global_header00006660000000000000000000000064146527471270014531gustar00rootroot0000000000000052 comment=4447c7562e3bc702ade25105912dce503f0c4010 abseil-20240722.0/000077500000000000000000000000001465274712700133725ustar00rootroot00000000000000abseil-20240722.0/.clang-format000066400000000000000000000000631465274712700157440ustar00rootroot00000000000000--- Language: Cpp BasedOnStyle: Google ... abseil-20240722.0/.github/000077500000000000000000000000001465274712700147325ustar00rootroot00000000000000abseil-20240722.0/.github/ISSUE_TEMPLATE/000077500000000000000000000000001465274712700171155ustar00rootroot00000000000000abseil-20240722.0/.github/ISSUE_TEMPLATE/00-bug_report.yml000066400000000000000000000040021465274712700222210ustar00rootroot00000000000000name: Bug Report description: Let us know that something does not work as expected. title: "[Bug]: Please title this bug report" body: - type: textarea id: what-happened attributes: label: Describe the issue description: What happened, and what did you expect to happen? validations: required: true - type: textarea id: steps attributes: label: Steps to reproduce the problem description: It is important that we are able to reproduce the problem that you are experiencing. Please provide all code and relevant steps to reproduce the problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the problem are also helpful. validations: required: true - type: textarea id: version attributes: label: What version of Abseil are you using? description: Please include the output of `git rev-parse HEAD` or the name of the LTS release that you are using. validations: required: true - type: textarea id: os attributes: label: What operating system and version are you using? description: If you are using a Linux distribution please include the name and version of the distribution as well. validations: required: true - type: textarea id: compiler attributes: label: What compiler and version are you using? description: Please include the output of `gcc -v` or `clang -v`, or the equivalent for your compiler. validations: required: true - type: textarea id: buildsystem attributes: label: What build system are you using? description: Please include the output of `bazel --version` or `cmake --version`, or the equivalent for your build system. validations: required: true - type: textarea id: additional attributes: label: Additional context description: Add any other context about the problem here. validations: required: false abseil-20240722.0/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000002571465274712700211110ustar00rootroot00000000000000blank_issues_enabled: false contact_links: - name: Question url: https://github.com/abseil/abseil-cpp/discussions about: Have a question? Ask us anything! :-) abseil-20240722.0/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000006111465274712700205310ustar00rootroot00000000000000Thank you for your contribution to Abseil! Before submitting this PR, please be sure to read our [contributing guidelines](https://github.com/abseil/abseil-cpp/blob/master/CONTRIBUTING.md). If you are a Googler, please also note that it is required that you send us a Piper CL instead of using the GitHub pull-request process. The code propagation process will deliver the change to GitHub. abseil-20240722.0/.gitignore000066400000000000000000000005351465274712700153650ustar00rootroot00000000000000# Bzlmod lockfile MODULE.bazel.lock # Ignore all bazel-* symlinks. /bazel-* # Ignore Bazel verbose explanations --verbose_explanations # Ignore CMake usual build directory build # Ignore Vim files *.swp # Ignore QtCreator Project file CMakeLists.txt.user # Ignore VS Code files .vscode/* # Ignore generated python artifacts *.pyc copts/__pycache__/ abseil-20240722.0/ABSEIL_ISSUE_TEMPLATE.md000066400000000000000000000021071465274712700171160ustar00rootroot00000000000000Please submit a new Abseil Issue using the template below: ## [Short title of proposed API change(s)] -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ## Background [Provide the background information that is required in order to evaluate the proposed API changes. No controversial claims should be made here. If there are design constraints that need to be considered, they should be presented here **along with justification for those constraints**. Linking to other docs is good, but please keep the **pertinent information as self contained** as possible in this section.] ## Proposed API Change (s) [Please clearly describe the API change(s) being proposed. If multiple changes, please keep them clearly distinguished. When possible, **use example code snippets to illustrate before-after API usages**. List pros-n-cons. Highlight the main questions that you want to be answered. Given the Abseil project compatibility requirements, describe why the API change is safe.] abseil-20240722.0/AUTHORS000066400000000000000000000004471465274712700144470ustar00rootroot00000000000000# This is the list of Abseil authors for copyright purposes. # # This does not necessarily list everyone who has contributed code, since in # some cases, their employer may be the copyright holder. To see the full list # of contributors, see the revision history in source control. Google Inc. abseil-20240722.0/BUILD.bazel000066400000000000000000000020301465274712700152430ustar00rootroot00000000000000# Copyright 2020 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. # package(default_visibility = ["//visibility:public"]) licenses(["notice"]) # Apache 2.0 # Expose license for external usage through bazel. exports_files([ "AUTHORS", "LICENSE", ]) # For building with clang-cl. # https://bazel.build/configure/windows#clang platform( name = "x64_windows-clang-cl", constraint_values = [ "@platforms//cpu:x86_64", "@platforms//os:windows", "@bazel_tools//tools/cpp:clang-cl", ], ) abseil-20240722.0/CMake/000077500000000000000000000000001465274712700143525ustar00rootroot00000000000000abseil-20240722.0/CMake/AbseilDll.cmake000066400000000000000000000634141465274712700172170ustar00rootroot00000000000000include(CMakeParseArguments) include(GNUInstallDirs) set(ABSL_INTERNAL_DLL_FILES "algorithm/algorithm.h" "algorithm/container.h" "base/attributes.h" "base/call_once.h" "base/casts.h" "base/config.h" "base/const_init.h" "base/dynamic_annotations.h" "base/internal/atomic_hook.h" "base/internal/cycleclock.cc" "base/internal/cycleclock.h" "base/internal/cycleclock_config.h" "base/internal/direct_mmap.h" "base/internal/dynamic_annotations.h" "base/internal/endian.h" "base/internal/errno_saver.h" "base/internal/fast_type_id.h" "base/internal/hide_ptr.h" "base/internal/identity.h" "base/internal/invoke.h" "base/internal/inline_variable.h" "base/internal/low_level_alloc.cc" "base/internal/low_level_alloc.h" "base/internal/low_level_scheduling.h" "base/internal/nullability_impl.h" "base/internal/per_thread_tls.h" "base/internal/poison.cc" "base/internal/poison.h" "base/prefetch.h" "base/internal/pretty_function.h" "base/internal/raw_logging.cc" "base/internal/raw_logging.h" "base/internal/scheduling_mode.h" "base/internal/scoped_set_env.cc" "base/internal/scoped_set_env.h" "base/internal/strerror.h" "base/internal/strerror.cc" "base/internal/spinlock.cc" "base/internal/spinlock.h" "base/internal/spinlock_wait.cc" "base/internal/spinlock_wait.h" "base/internal/sysinfo.cc" "base/internal/sysinfo.h" "base/internal/thread_identity.cc" "base/internal/thread_identity.h" "base/internal/throw_delegate.cc" "base/internal/throw_delegate.h" "base/internal/tsan_mutex_interface.h" "base/internal/unaligned_access.h" "base/internal/unscaledcycleclock.cc" "base/internal/unscaledcycleclock.h" "base/internal/unscaledcycleclock_config.h" "base/log_severity.cc" "base/log_severity.h" "base/macros.h" "base/no_destructor.h" "base/nullability.h" "base/optimization.h" "base/options.h" "base/policy_checks.h" "base/port.h" "base/thread_annotations.h" "cleanup/cleanup.h" "cleanup/internal/cleanup.h" "container/btree_map.h" "container/btree_set.h" "container/hash_container_defaults.h" "container/fixed_array.h" "container/flat_hash_map.h" "container/flat_hash_set.h" "container/inlined_vector.h" "container/internal/btree.h" "container/internal/btree_container.h" "container/internal/common.h" "container/internal/common_policy_traits.h" "container/internal/compressed_tuple.h" "container/internal/container_memory.h" "container/internal/hash_function_defaults.h" "container/internal/hash_policy_traits.h" "container/internal/hashtable_debug.h" "container/internal/hashtable_debug_hooks.h" "container/internal/hashtablez_sampler.cc" "container/internal/hashtablez_sampler.h" "container/internal/hashtablez_sampler_force_weak_definition.cc" "container/internal/inlined_vector.h" "container/internal/layout.h" "container/internal/node_slot_policy.h" "container/internal/raw_hash_map.h" "container/internal/raw_hash_set.cc" "container/internal/raw_hash_set.h" "container/internal/tracked.h" "container/node_hash_map.h" "container/node_hash_set.h" "crc/crc32c.cc" "crc/crc32c.h" "crc/internal/cpu_detect.cc" "crc/internal/cpu_detect.h" "crc/internal/crc32c.h" "crc/internal/crc32c_inline.h" "crc/internal/crc32_x86_arm_combined_simd.h" "crc/internal/crc.cc" "crc/internal/crc.h" "crc/internal/crc_cord_state.cc" "crc/internal/crc_cord_state.h" "crc/internal/crc_internal.h" "crc/internal/crc_x86_arm_combined.cc" "crc/internal/crc_memcpy_fallback.cc" "crc/internal/crc_memcpy.h" "crc/internal/crc_memcpy_x86_arm_combined.cc" "crc/internal/crc_non_temporal_memcpy.cc" "crc/internal/crc_x86_arm_combined.cc" "crc/internal/non_temporal_arm_intrinsics.h" "crc/internal/non_temporal_memcpy.h" "debugging/failure_signal_handler.cc" "debugging/failure_signal_handler.h" "debugging/leak_check.h" "debugging/stacktrace.cc" "debugging/stacktrace.h" "debugging/symbolize.cc" "debugging/symbolize.h" "debugging/internal/address_is_readable.cc" "debugging/internal/address_is_readable.h" "debugging/internal/bounded_utf8_length_sequence.h" "debugging/internal/decode_rust_punycode.cc" "debugging/internal/decode_rust_punycode.h" "debugging/internal/demangle.cc" "debugging/internal/demangle.h" "debugging/internal/demangle_rust.cc" "debugging/internal/demangle_rust.h" "debugging/internal/elf_mem_image.cc" "debugging/internal/elf_mem_image.h" "debugging/internal/examine_stack.cc" "debugging/internal/examine_stack.h" "debugging/internal/stack_consumption.cc" "debugging/internal/stack_consumption.h" "debugging/internal/stacktrace_config.h" "debugging/internal/symbolize.h" "debugging/internal/utf8_for_code_point.cc" "debugging/internal/utf8_for_code_point.h" "debugging/internal/vdso_support.cc" "debugging/internal/vdso_support.h" "functional/any_invocable.h" "functional/internal/front_binder.h" "functional/bind_front.h" "functional/function_ref.h" "functional/internal/any_invocable.h" "functional/internal/function_ref.h" "functional/overload.h" "hash/hash.h" "hash/internal/city.h" "hash/internal/city.cc" "hash/internal/hash.h" "hash/internal/hash.cc" "hash/internal/spy_hash_state.h" "hash/internal/low_level_hash.h" "hash/internal/low_level_hash.cc" "log/absl_check.h" "log/absl_log.h" "log/absl_vlog_is_on.h" "log/check.h" "log/die_if_null.cc" "log/die_if_null.h" "log/globals.cc" "log/globals.h" "log/internal/append_truncated.h" "log/internal/check_impl.h" "log/internal/check_op.cc" "log/internal/check_op.h" "log/internal/conditions.cc" "log/internal/conditions.h" "log/internal/config.h" "log/internal/fnmatch.h" "log/internal/fnmatch.cc" "log/internal/globals.cc" "log/internal/globals.h" "log/internal/log_format.cc" "log/internal/log_format.h" "log/internal/log_impl.h" "log/internal/log_message.cc" "log/internal/log_message.h" "log/internal/log_sink_set.cc" "log/internal/log_sink_set.h" "log/internal/nullguard.cc" "log/internal/nullguard.h" "log/internal/nullstream.h" "log/internal/proto.h" "log/internal/proto.cc" "log/internal/strip.h" "log/internal/structured.h" "log/internal/vlog_config.cc" "log/internal/vlog_config.h" "log/internal/voidify.h" "log/initialize.cc" "log/initialize.h" "log/log.h" "log/log_entry.cc" "log/log_entry.h" "log/log_sink.cc" "log/log_sink.h" "log/log_sink_registry.h" "log/log_streamer.h" "log/structured.h" "log/vlog_is_on.h" "memory/memory.h" "meta/type_traits.h" "numeric/bits.h" "numeric/int128.cc" "numeric/int128.h" "numeric/internal/bits.h" "numeric/internal/representation.h" "profiling/internal/exponential_biased.cc" "profiling/internal/exponential_biased.h" "profiling/internal/periodic_sampler.cc" "profiling/internal/periodic_sampler.h" "profiling/internal/sample_recorder.h" "random/bernoulli_distribution.h" "random/beta_distribution.h" "random/bit_gen_ref.h" "random/discrete_distribution.cc" "random/discrete_distribution.h" "random/distributions.h" "random/exponential_distribution.h" "random/gaussian_distribution.cc" "random/gaussian_distribution.h" "random/internal/distribution_caller.h" "random/internal/fastmath.h" "random/internal/fast_uniform_bits.h" "random/internal/generate_real.h" "random/internal/iostream_state_saver.h" "random/internal/nonsecure_base.h" "random/internal/pcg_engine.h" "random/internal/platform.h" "random/internal/pool_urbg.cc" "random/internal/pool_urbg.h" "random/internal/randen.cc" "random/internal/randen.h" "random/internal/randen_detect.cc" "random/internal/randen_detect.h" "random/internal/randen_engine.h" "random/internal/randen_hwaes.cc" "random/internal/randen_hwaes.h" "random/internal/randen_round_keys.cc" "random/internal/randen_slow.cc" "random/internal/randen_slow.h" "random/internal/randen_traits.h" "random/internal/salted_seed_seq.h" "random/internal/seed_material.cc" "random/internal/seed_material.h" "random/internal/sequence_urbg.h" "random/internal/traits.h" "random/internal/uniform_helper.h" "random/internal/wide_multiply.h" "random/log_uniform_int_distribution.h" "random/poisson_distribution.h" "random/random.h" "random/seed_gen_exception.cc" "random/seed_gen_exception.h" "random/seed_sequences.cc" "random/seed_sequences.h" "random/uniform_int_distribution.h" "random/uniform_real_distribution.h" "random/zipf_distribution.h" "status/internal/status_internal.h" "status/internal/status_internal.cc" "status/internal/statusor_internal.h" "status/status.h" "status/status.cc" "status/statusor.h" "status/statusor.cc" "status/status_payload_printer.h" "status/status_payload_printer.cc" "strings/ascii.cc" "strings/ascii.h" "strings/charconv.cc" "strings/charconv.h" "strings/charset.h" "strings/cord.cc" "strings/cord.h" "strings/cord_analysis.cc" "strings/cord_analysis.h" "strings/cord_buffer.cc" "strings/cord_buffer.h" "strings/escaping.cc" "strings/escaping.h" "strings/internal/charconv_bigint.cc" "strings/internal/charconv_bigint.h" "strings/internal/charconv_parse.cc" "strings/internal/charconv_parse.h" "strings/internal/cord_data_edge.h" "strings/internal/cord_internal.cc" "strings/internal/cord_internal.h" "strings/internal/cord_rep_btree.cc" "strings/internal/cord_rep_btree.h" "strings/internal/cord_rep_btree_navigator.cc" "strings/internal/cord_rep_btree_navigator.h" "strings/internal/cord_rep_btree_reader.cc" "strings/internal/cord_rep_btree_reader.h" "strings/internal/cord_rep_crc.cc" "strings/internal/cord_rep_crc.h" "strings/internal/cord_rep_consume.h" "strings/internal/cord_rep_consume.cc" "strings/internal/cord_rep_flat.h" "strings/internal/cordz_functions.cc" "strings/internal/cordz_functions.h" "strings/internal/cordz_handle.cc" "strings/internal/cordz_handle.h" "strings/internal/cordz_info.cc" "strings/internal/cordz_info.h" "strings/internal/cordz_sample_token.cc" "strings/internal/cordz_sample_token.h" "strings/internal/cordz_statistics.h" "strings/internal/cordz_update_scope.h" "strings/internal/cordz_update_tracker.h" "strings/internal/damerau_levenshtein_distance.h" "strings/internal/damerau_levenshtein_distance.cc" "strings/internal/stl_type_traits.h" "strings/internal/string_constant.h" "strings/internal/stringify_sink.h" "strings/internal/stringify_sink.cc" "strings/has_absl_stringify.h" "strings/has_ostream_operator.h" "strings/match.cc" "strings/match.h" "strings/numbers.cc" "strings/numbers.h" "strings/str_format.h" "strings/str_cat.cc" "strings/str_cat.h" "strings/str_join.h" "strings/str_replace.cc" "strings/str_replace.h" "strings/str_split.cc" "strings/str_split.h" "strings/string_view.cc" "strings/string_view.h" "strings/strip.h" "strings/substitute.cc" "strings/substitute.h" "strings/internal/escaping.h" "strings/internal/escaping.cc" "strings/internal/memutil.cc" "strings/internal/memutil.h" "strings/internal/ostringstream.cc" "strings/internal/ostringstream.h" "strings/internal/pow10_helper.cc" "strings/internal/pow10_helper.h" "strings/internal/resize_uninitialized.h" "strings/internal/str_format/arg.cc" "strings/internal/str_format/arg.h" "strings/internal/str_format/bind.cc" "strings/internal/str_format/bind.h" "strings/internal/str_format/checker.h" "strings/internal/str_format/constexpr_parser.h" "strings/internal/str_format/extension.cc" "strings/internal/str_format/extension.h" "strings/internal/str_format/float_conversion.cc" "strings/internal/str_format/float_conversion.h" "strings/internal/str_format/output.cc" "strings/internal/str_format/output.h" "strings/internal/str_format/parser.cc" "strings/internal/str_format/parser.h" "strings/internal/str_join_internal.h" "strings/internal/str_split_internal.h" "strings/internal/utf8.cc" "strings/internal/utf8.h" "synchronization/barrier.cc" "synchronization/barrier.h" "synchronization/blocking_counter.cc" "synchronization/blocking_counter.h" "synchronization/mutex.cc" "synchronization/mutex.h" "synchronization/notification.cc" "synchronization/notification.h" "synchronization/internal/create_thread_identity.cc" "synchronization/internal/create_thread_identity.h" "synchronization/internal/futex.h" "synchronization/internal/futex_waiter.h" "synchronization/internal/futex_waiter.cc" "synchronization/internal/graphcycles.cc" "synchronization/internal/graphcycles.h" "synchronization/internal/kernel_timeout.h" "synchronization/internal/kernel_timeout.cc" "synchronization/internal/per_thread_sem.cc" "synchronization/internal/per_thread_sem.h" "synchronization/internal/pthread_waiter.h" "synchronization/internal/pthread_waiter.cc" "synchronization/internal/sem_waiter.h" "synchronization/internal/sem_waiter.cc" "synchronization/internal/stdcpp_waiter.h" "synchronization/internal/stdcpp_waiter.cc" "synchronization/internal/thread_pool.h" "synchronization/internal/waiter.h" "synchronization/internal/waiter_base.h" "synchronization/internal/waiter_base.cc" "synchronization/internal/win32_waiter.h" "synchronization/internal/win32_waiter.cc" "time/civil_time.cc" "time/civil_time.h" "time/clock.cc" "time/clock.h" "time/duration.cc" "time/format.cc" "time/time.cc" "time/time.h" "time/internal/cctz/include/cctz/civil_time.h" "time/internal/cctz/include/cctz/civil_time_detail.h" "time/internal/cctz/include/cctz/time_zone.h" "time/internal/cctz/include/cctz/zone_info_source.h" "time/internal/cctz/src/civil_time_detail.cc" "time/internal/cctz/src/time_zone_fixed.cc" "time/internal/cctz/src/time_zone_fixed.h" "time/internal/cctz/src/time_zone_format.cc" "time/internal/cctz/src/time_zone_if.cc" "time/internal/cctz/src/time_zone_if.h" "time/internal/cctz/src/time_zone_impl.cc" "time/internal/cctz/src/time_zone_impl.h" "time/internal/cctz/src/time_zone_info.cc" "time/internal/cctz/src/time_zone_info.h" "time/internal/cctz/src/time_zone_libc.cc" "time/internal/cctz/src/time_zone_libc.h" "time/internal/cctz/src/time_zone_lookup.cc" "time/internal/cctz/src/time_zone_posix.cc" "time/internal/cctz/src/time_zone_posix.h" "time/internal/cctz/src/tzfile.h" "time/internal/cctz/src/zone_info_source.cc" "types/any.h" "types/bad_any_cast.cc" "types/bad_any_cast.h" "types/bad_optional_access.cc" "types/bad_optional_access.h" "types/bad_variant_access.cc" "types/bad_variant_access.h" "types/compare.h" "types/internal/variant.h" "types/optional.h" "types/internal/optional.h" "types/span.h" "types/internal/span.h" "types/variant.h" "utility/internal/if_constexpr.h" "utility/utility.h" "debugging/leak_check.cc" ) if(NOT MSVC) list(APPEND ABSL_INTERNAL_DLL_FILES "flags/commandlineflag.cc" "flags/commandlineflag.h" "flags/config.h" "flags/declare.h" "flags/flag.h" "flags/internal/commandlineflag.cc" "flags/internal/commandlineflag.h" "flags/internal/flag.cc" "flags/internal/flag.h" "flags/internal/parse.h" "flags/internal/path_util.h" "flags/internal/private_handle_accessor.cc" "flags/internal/private_handle_accessor.h" "flags/internal/program_name.cc" "flags/internal/program_name.h" "flags/internal/registry.h" "flags/internal/sequence_lock.h" "flags/internal/usage.cc" "flags/internal/usage.h" "flags/marshalling.cc" "flags/marshalling.h" "flags/parse.cc" "flags/parse.h" "flags/reflection.cc" "flags/reflection.h" "flags/usage.cc" "flags/usage.h" "flags/usage_config.cc" "flags/usage_config.h" "log/flags.cc" "log/flags.h" "log/internal/flags.h" ) endif() set(ABSL_INTERNAL_DLL_TARGETS "absl_check" "absl_log" "absl_vlog_is_on" "algorithm" "algorithm_container" "any" "any_invocable" "atomic_hook" "bad_any_cast" "bad_any_cast_impl" "bad_optional_access" "bad_variant_access" "base" "base_internal" "bind_front" "bits" "btree" "check" "city" "civil_time" "compare" "compressed_tuple" "config" "container" "container_common" "container_memory" "cord" "cord_internal" "cordz_functions" "cordz_handle" "cordz_info" "cordz_sample_token" "core_headers" "counting_allocator" "crc_cord_state" "crc_cpu_detect" "crc_internal" "crc32c" "debugging" "debugging_internal" "demangle_internal" "die_if_null" "dynamic_annotations" "endian" "examine_stack" "exponential_biased" "failure_signal_handler" "fixed_array" "flat_hash_map" "flat_hash_set" "function_ref" "graphcycles_internal" "hash" "hash_function_defaults" "hash_policy_traits" "hashtable_debug" "hashtable_debug_hooks" "hashtablez_sampler" "inlined_vector" "inlined_vector_internal" "int128" "kernel_timeout_internal" "layout" "leak_check" "log_internal_check_impl" "log_internal_check_op" "log_internal_conditions" "log_internal_config" "log_internal_fnmatch" "log_internal_format" "log_internal_globals" "log_internal_log_impl" "log_internal_proto" "log_internal_message" "log_internal_log_sink_set" "log_internal_nullguard" "log_internal_nullstream" "log_internal_strip" "log_internal_voidify" "log_internal_append_truncated" "log_globals" "log_initialize" "log" "log_entry" "log_sink" "log_sink_registry" "log_streamer" "log_internal_structured" "log_severity" "log_structured" "low_level_hash" "malloc_internal" "memory" "meta" "node_hash_map" "node_hash_set" "node_slot_policy" "non_temporal_arm_intrinsics" "non_temporal_memcpy" "numeric" "optional" "periodic_sampler" "pow10_helper" "pretty_function" "random_bit_gen_ref" "random_distributions" "random_internal_distribution_caller" "random_internal_distributions" "random_internal_explicit_seed_seq" "random_internal_fastmath" "random_internal_fast_uniform_bits" "random_internal_generate_real" "random_internal_iostream_state_saver" "random_internal_nonsecure_base" "random_internal_pcg_engine" "random_internal_platform" "random_internal_pool_urbg" "random_internal_randen" "random_internal_randen_engine" "random_internal_randen_hwaes" "random_internal_randen_hwaes_impl" "random_internal_randen_slow" "random_internal_salted_seed_seq" "random_internal_seed_material" "random_internal_sequence_urbg" "random_internal_traits" "random_internal_uniform_helper" "random_internal_wide_multiply" "random_random" "random_seed_gen_exception" "random_seed_sequences" "raw_hash_map" "raw_hash_set" "raw_logging_internal" "sample_recorder" "scoped_set_env" "span" "spinlock_wait" "spy_hash_state" "stack_consumption" "stacktrace" "status" "statusor" "str_format" "str_format_internal" "strerror" "strings" "strings_internal" "string_view" "symbolize" "synchronization" "thread_pool" "throw_delegate" "time" "time_zone" "tracked" "type_traits" "utility" "variant" "vlog_config_internal" "vlog_is_on" ) if(NOT MSVC) list(APPEND ABSL_INTERNAL_DLL_TARGETS "flags" "flags_commandlineflag" "flags_commandlineflag_internal" "flags_config" "flags_internal" "flags_marshalling" "flags_parse" "flags_path_util" "flags_private_handle_accessor" "flags_program_name" "flags_reflection" "flags_usage" "flags_usage_internal" "log_internal_flags" "log_flags" ) endif() set(ABSL_INTERNAL_TEST_DLL_FILES "hash/hash_testing.h" "log/scoped_mock_log.cc" "log/scoped_mock_log.h" "random/internal/chi_square.cc" "random/internal/chi_square.h" "random/internal/distribution_test_util.cc" "random/internal/distribution_test_util.h" "random/internal/mock_helpers.h" "random/internal/mock_overload_set.h" "random/mocking_bit_gen.h" "random/mock_distributions.h" "status/status_matchers.h" "status/internal/status_matchers.cc" "status/internal/status_matchers.h" "strings/cordz_test_helpers.h" "strings/cord_test_helpers.h" ) set(ABSL_INTERNAL_TEST_DLL_TARGETS "cord_test_helpers" "cordz_test_helpers" "hash_testing" "random_mocking_bit_gen" "random_internal_distribution_test_util" "random_internal_mock_overload_set" "scoped_mock_log" "status_matchers" ) include(CheckCXXSourceCompiles) check_cxx_source_compiles( [==[ #ifdef _MSC_VER # if _MSVC_LANG < 201703L # error "The compiler defaults or is configured for C++ < 17" # endif #elif __cplusplus < 201703L # error "The compiler defaults or is configured for C++ < 17" #endif int main() { return 0; } ]==] ABSL_INTERNAL_AT_LEAST_CXX17) check_cxx_source_compiles( [==[ #ifdef _MSC_VER # if _MSVC_LANG < 202002L # error "The compiler defaults or is configured for C++ < 20" # endif #elif __cplusplus < 202002L # error "The compiler defaults or is configured for C++ < 20" #endif int main() { return 0; } ]==] ABSL_INTERNAL_AT_LEAST_CXX20) if(ABSL_INTERNAL_AT_LEAST_CXX20) set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_20) elseif(ABSL_INTERNAL_AT_LEAST_CXX17) set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_17) else() set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_14) endif() function(absl_internal_dll_contains) cmake_parse_arguments(ABSL_INTERNAL_DLL "" "OUTPUT;TARGET" "" ${ARGN} ) STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_DLL_TARGET}) if (_target IN_LIST ABSL_INTERNAL_DLL_TARGETS) set(${ABSL_INTERNAL_DLL_OUTPUT} 1 PARENT_SCOPE) else() set(${ABSL_INTERNAL_DLL_OUTPUT} 0 PARENT_SCOPE) endif() endfunction() function(absl_internal_test_dll_contains) cmake_parse_arguments(ABSL_INTERNAL_TEST_DLL "" "OUTPUT;TARGET" "" ${ARGN} ) STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_TEST_DLL_TARGET}) if (_target IN_LIST ABSL_INTERNAL_TEST_DLL_TARGETS) set(${ABSL_INTERNAL_TEST_DLL_OUTPUT} 1 PARENT_SCOPE) else() set(${ABSL_INTERNAL_TEST_DLL_OUTPUT} 0 PARENT_SCOPE) endif() endfunction() function(absl_internal_dll_targets) cmake_parse_arguments(ABSL_INTERNAL_DLL "" "OUTPUT" "DEPS" ${ARGN} ) set(_deps "") foreach(dep IN LISTS ABSL_INTERNAL_DLL_DEPS) absl_internal_dll_contains(TARGET ${dep} OUTPUT _dll_contains) absl_internal_test_dll_contains(TARGET ${dep} OUTPUT _test_dll_contains) if (_dll_contains) list(APPEND _deps abseil_dll) elseif (_test_dll_contains) list(APPEND _deps abseil_test_dll) else() list(APPEND _deps ${dep}) endif() endforeach() # Because we may have added the DLL multiple times list(REMOVE_DUPLICATES _deps) set(${ABSL_INTERNAL_DLL_OUTPUT} "${_deps}" PARENT_SCOPE) endfunction() function(absl_make_dll) cmake_parse_arguments(ABSL_INTERNAL_MAKE_DLL "" "TEST" "" ${ARGN} ) if (ABSL_INTERNAL_MAKE_DLL_TEST) set(_dll "abseil_test_dll") set(_dll_files ${ABSL_INTERNAL_TEST_DLL_FILES}) set(_dll_libs "abseil_dll" "GTest::gtest" "GTest::gmock") set(_dll_compile_definitions "GTEST_LINKED_AS_SHARED_LIBRARY=1") set(_dll_includes ${absl_gtest_src_dir}/googletest/include ${absl_gtest_src_dir}/googlemock/include) set(_dll_consume "ABSL_CONSUME_TEST_DLL") set(_dll_build "ABSL_BUILD_TEST_DLL") else() set(_dll "abseil_dll") set(_dll_files ${ABSL_INTERNAL_DLL_FILES}) set(_dll_libs Threads::Threads # TODO(#1495): Use $ once our # minimum CMake version >= 3.24 $<$:-Wl,-framework,CoreFoundation> ) set(_dll_compile_definitions "") set(_dll_includes "") set(_dll_consume "ABSL_CONSUME_DLL") set(_dll_build "ABSL_BUILD_DLL") endif() add_library( ${_dll} SHARED ${_dll_files} ) target_link_libraries( ${_dll} PRIVATE ${_dll_libs} ${ABSL_DEFAULT_LINKOPTS} ) set_target_properties(${_dll} PROPERTIES LINKER_LANGUAGE "CXX" SOVERSION ${ABSL_SOVERSION} ) target_include_directories( ${_dll} PUBLIC "$" $ PRIVATE ${_dll_includes} ) target_compile_options( ${_dll} PRIVATE ${ABSL_DEFAULT_COPTS} ) foreach(cflag ${ABSL_CC_LIB_COPTS}) if(${cflag} MATCHES "^(-Wno|/wd)") # These flags are needed to suppress warnings that might fire in our headers. set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") elseif(${cflag} MATCHES "^(-W|/w[1234eo])") # Don't impose our warnings on others. else() set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") endif() endforeach() string(REPLACE ";" " " PC_LINKOPTS "${ABSL_CC_LIB_LINKOPTS}") FILE(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/lib/pkgconfig/${_dll}.pc" CONTENT "\ prefix=${CMAKE_INSTALL_PREFIX}\n\ exec_prefix=\${prefix}\n\ libdir=${CMAKE_INSTALL_FULL_LIBDIR}\n\ includedir=${CMAKE_INSTALL_FULL_INCLUDEDIR}\n\ \n\ Name: ${_dll}\n\ Description: Abseil DLL library\n\ URL: https://abseil.io/\n\ Version: ${absl_VERSION}\n\ Libs: -L\${libdir} $<$>:-l${_dll}> ${PC_LINKOPTS}\n\ Cflags: -I\${includedir}${PC_CFLAGS}\n") INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/${_dll}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") target_compile_definitions( ${_dll} PUBLIC ${_dll_compile_definitions} PRIVATE ${_dll_build} NOMINMAX INTERFACE ${ABSL_CC_LIB_DEFINES} ${_dll_consume} ) if(ABSL_PROPAGATE_CXX_STD) # Abseil libraries require C++14 as the current minimum standard. When # compiled with a higher minimum (either because it is the compiler's # default or explicitly requested), then Abseil requires that standard. target_compile_features(${_dll} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE}) endif() install(TARGETS ${_dll} EXPORT ${PROJECT_NAME}Targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) add_library(absl::${_dll} ALIAS ${_dll}) endfunction() abseil-20240722.0/CMake/AbseilHelpers.cmake000066400000000000000000000353021465274712700201010ustar00rootroot00000000000000# # Copyright 2017 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(CMakeParseArguments) include(AbseilConfigureCopts) include(AbseilDll) # The IDE folder for Abseil that will be used if Abseil is included in a CMake # project that sets # set_property(GLOBAL PROPERTY USE_FOLDERS ON) # For example, Visual Studio supports folders. if(NOT DEFINED ABSL_IDE_FOLDER) set(ABSL_IDE_FOLDER Abseil) endif() if(ABSL_USE_SYSTEM_INCLUDES) set(ABSL_INTERNAL_INCLUDE_WARNING_GUARD SYSTEM) else() set(ABSL_INTERNAL_INCLUDE_WARNING_GUARD "") endif() # absl_cc_library() # # CMake function to imitate Bazel's cc_library rule. # # Parameters: # NAME: name of target (see Note) # HDRS: List of public header files for the library # SRCS: List of source files for the library # DEPS: List of other libraries to be linked in to the binary targets # COPTS: List of private compile options # DEFINES: List of public defines # LINKOPTS: List of link options # PUBLIC: Add this so that this library will be exported under absl:: # Also in IDE, target will appear in Abseil folder while non PUBLIC will be in Abseil/internal. # TESTONLY: When added, this target will only be built if both # BUILD_TESTING=ON and ABSL_BUILD_TESTING=ON. # # Note: # By default, absl_cc_library will always create a library named absl_${NAME}, # and alias target absl::${NAME}. The absl:: form should always be used. # This is to reduce namespace pollution. # # absl_cc_library( # NAME # awesome # HDRS # "a.h" # SRCS # "a.cc" # ) # absl_cc_library( # NAME # fantastic_lib # SRCS # "b.cc" # DEPS # absl::awesome # not "awesome" ! # PUBLIC # ) # # absl_cc_library( # NAME # main_lib # ... # DEPS # absl::fantastic_lib # ) # # TODO(b/320467376): Implement "ALWAYSLINK". function(absl_cc_library) cmake_parse_arguments(ABSL_CC_LIB "DISABLE_INSTALL;PUBLIC;TESTONLY" "NAME" "HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DEPS" ${ARGN} ) if(ABSL_CC_LIB_TESTONLY AND NOT ((BUILD_TESTING AND ABSL_BUILD_TESTING) OR (ABSL_BUILD_TEST_HELPERS AND ABSL_CC_LIB_PUBLIC))) return() endif() 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 # 16.04 LTS) only come with cmake 3.5 by default. For this reason, we can't # use list(FILTER...) set(ABSL_CC_SRCS "${ABSL_CC_LIB_SRCS}") foreach(src_file IN LISTS ABSL_CC_SRCS) if(${src_file} MATCHES ".*\\.(h|inc)") list(REMOVE_ITEM ABSL_CC_SRCS "${src_file}") endif() endforeach() if(ABSL_CC_SRCS STREQUAL "") set(ABSL_CC_LIB_IS_INTERFACE 1) else() set(ABSL_CC_LIB_IS_INTERFACE 0) endif() # Determine this build target's relationship to the DLL. It's one of four things: # 1. "dll" -- This target is part of the DLL # 2. "dll_dep" -- This target is not part of the DLL, but depends on the DLL. # Note that we assume any target not in the DLL depends on the # DLL. This is not a technical necessity but a convenience # which happens to be true, because nearly every target is # part of the DLL. # 3. "shared" -- This is a shared library, perhaps on a non-windows platform # where DLL doesn't make sense. # 4. "static" -- This target does not depend on the DLL and should be built # statically. if (${ABSL_BUILD_DLL}) if(ABSL_ENABLE_INSTALL) absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll) absl_internal_test_dll_contains(TARGET ${_NAME} OUTPUT _in_test_dll) else() absl_internal_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_dll) absl_internal_test_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_test_dll) endif() if (${_in_dll} OR ${_in_test_dll}) # This target should be replaced by the DLL set(_build_type "dll") set(ABSL_CC_LIB_IS_INTERFACE 1) else() # Building a DLL, but this target is not part of the DLL set(_build_type "dll_dep") endif() elseif(BUILD_SHARED_LIBS) set(_build_type "shared") else() set(_build_type "static") endif() # Generate a pkg-config file for every library: if(ABSL_ENABLE_INSTALL) if(absl_VERSION) set(PC_VERSION "${absl_VERSION}") else() set(PC_VERSION "head") endif() if(NOT _build_type STREQUAL "dll") set(LNK_LIB "${LNK_LIB} -labsl_${_NAME}") endif() foreach(dep ${ABSL_CC_LIB_DEPS}) if(${dep} MATCHES "^absl::(.*)") # for DLL builds many libs are not created, but add # the pkgconfigs nevertheless, pointing to the dll. if(_build_type STREQUAL "dll") # hide this MATCHES in an if-clause so it doesn't overwrite # the CMAKE_MATCH_1 from (${dep} MATCHES "^absl::(.*)") if(NOT PC_DEPS MATCHES "abseil_dll") # Join deps with commas. if(PC_DEPS) set(PC_DEPS "${PC_DEPS},") endif() # don't duplicate dll-dep if it exists already set(PC_DEPS "${PC_DEPS} abseil_dll = ${PC_VERSION}") set(LNK_LIB "${LNK_LIB} -labseil_dll") endif() else() # Join deps with commas. if(PC_DEPS) set(PC_DEPS "${PC_DEPS},") endif() set(PC_DEPS "${PC_DEPS} absl_${CMAKE_MATCH_1} = ${PC_VERSION}") endif() endif() endforeach() set(skip_next_cflag OFF) foreach(cflag ${ABSL_CC_LIB_COPTS}) if(skip_next_cflag) set(skip_next_cflag OFF) elseif(${cflag} MATCHES "^-Xarch_") # An -Xarch_ flag implies that its successor only applies to the # specified platform. Filter both of them out before the successor # reaches the "^-m" filter. set(skip_next_cflag ON) elseif(${cflag} MATCHES "^(-Wno|/wd)") # These flags are needed to suppress warnings that might fire in our headers. set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") elseif(${cflag} MATCHES "^(-W|/w[1234eo])") # Don't impose our warnings on others. elseif(${cflag} MATCHES "^-m") # Don't impose CPU instruction requirements on others, as # the code performs feature detection on runtime. else() set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") endif() endforeach() string(REPLACE ";" " " PC_LINKOPTS "${ABSL_CC_LIB_LINKOPTS}") FILE(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" CONTENT "\ prefix=${CMAKE_INSTALL_PREFIX}\n\ exec_prefix=\${prefix}\n\ libdir=${CMAKE_INSTALL_FULL_LIBDIR}\n\ includedir=${CMAKE_INSTALL_FULL_INCLUDEDIR}\n\ \n\ Name: absl_${_NAME}\n\ Description: Abseil ${_NAME} library\n\ URL: https://abseil.io/\n\ Version: ${PC_VERSION}\n\ Requires:${PC_DEPS}\n\ Libs: -L\${libdir} $<$>:${LNK_LIB}> ${PC_LINKOPTS}\n\ Cflags: -I\${includedir}${PC_CFLAGS}\n") INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") endif() if(NOT ABSL_CC_LIB_IS_INTERFACE) if(_build_type STREQUAL "dll_dep") # This target depends on the DLL. When adding dependencies to this target, # any depended-on-target which is contained inside the DLL is replaced # with a dependency on the DLL. add_library(${_NAME} STATIC "") target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) absl_internal_dll_targets( DEPS ${ABSL_CC_LIB_DEPS} OUTPUT _dll_deps ) target_link_libraries(${_NAME} PUBLIC ${_dll_deps} PRIVATE ${ABSL_CC_LIB_LINKOPTS} ${ABSL_DEFAULT_LINKOPTS} ) if (ABSL_CC_LIB_TESTONLY) set(_gtest_link_define "GTEST_LINKED_AS_SHARED_LIBRARY=1") else() set(_gtest_link_define) endif() target_compile_definitions(${_NAME} PUBLIC ABSL_CONSUME_DLL "${_gtest_link_define}" ) elseif(_build_type STREQUAL "static" OR _build_type STREQUAL "shared") add_library(${_NAME} "") target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) if(APPLE) set_target_properties(${_NAME} PROPERTIES INSTALL_RPATH "@loader_path") elseif(UNIX) set_target_properties(${_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN") endif() target_link_libraries(${_NAME} PUBLIC ${ABSL_CC_LIB_DEPS} PRIVATE ${ABSL_CC_LIB_LINKOPTS} ${ABSL_DEFAULT_LINKOPTS} ) else() message(FATAL_ERROR "Invalid build type: ${_build_type}") endif() # Linker language can be inferred from sources, but in the case of DLLs we # don't have any .cc files so it would be ambiguous. We could set it # explicitly only in the case of DLLs but, because "CXX" is always the # correct linker language for static or for shared libraries, we set it # unconditionally. set_property(TARGET ${_NAME} PROPERTY LINKER_LANGUAGE "CXX") target_include_directories(${_NAME} ${ABSL_INTERNAL_INCLUDE_WARNING_GUARD} PUBLIC "$" $ ) target_compile_options(${_NAME} PRIVATE ${ABSL_CC_LIB_COPTS}) target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES}) # Add all Abseil targets to a a folder in the IDE for organization. if(ABSL_CC_LIB_PUBLIC) set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}) elseif(ABSL_CC_LIB_TESTONLY) set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test) else() set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal) endif() if(ABSL_PROPAGATE_CXX_STD) # Abseil libraries require C++14 as the current minimum standard. When # compiled with a higher standard (either because it is the compiler's # default or explicitly requested), then Abseil requires that standard. target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE}) endif() # When being installed, we lose the absl_ prefix. We want to put it back # to have properly named lib files. This is a no-op when we are not being # installed. if(ABSL_ENABLE_INSTALL) set_target_properties(${_NAME} PROPERTIES OUTPUT_NAME "absl_${_NAME}" SOVERSION "${ABSL_SOVERSION}" ) endif() else() # Generating header-only library add_library(${_NAME} INTERFACE) target_include_directories(${_NAME} ${ABSL_INTERNAL_INCLUDE_WARNING_GUARD} INTERFACE "$" $ ) if (_build_type STREQUAL "dll") set(ABSL_CC_LIB_DEPS abseil_dll) endif() target_link_libraries(${_NAME} INTERFACE ${ABSL_CC_LIB_DEPS} ${ABSL_CC_LIB_LINKOPTS} ${ABSL_DEFAULT_LINKOPTS} ) target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES}) if(ABSL_PROPAGATE_CXX_STD) # Abseil libraries require C++14 as the current minimum standard. # Top-level application CMake projects should ensure a consistent C++ # standard for all compiled sources by setting CMAKE_CXX_STANDARD. target_compile_features(${_NAME} INTERFACE ${ABSL_INTERNAL_CXX_STD_FEATURE}) endif() endif() if(ABSL_ENABLE_INSTALL) install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME}) endfunction() # absl_cc_test() # # CMake function to imitate Bazel's cc_test rule. # # Parameters: # NAME: name of target (see Usage below) # SRCS: List of source files for the binary # DEPS: List of other libraries to be linked in to the binary targets # COPTS: List of private compile options # DEFINES: List of public defines # LINKOPTS: List of link options # # Note: # By default, absl_cc_test will always create a binary named absl_${NAME}. # This will also add it to ctest list as absl_${NAME}. # # Usage: # absl_cc_library( # NAME # awesome # HDRS # "a.h" # SRCS # "a.cc" # PUBLIC # ) # # absl_cc_test( # NAME # awesome_test # SRCS # "awesome_test.cc" # DEPS # absl::awesome # GTest::gmock # GTest::gtest_main # ) function(absl_cc_test) if(NOT (BUILD_TESTING AND ABSL_BUILD_TESTING)) return() endif() cmake_parse_arguments(ABSL_CC_TEST "" "NAME" "SRCS;COPTS;DEFINES;LINKOPTS;DEPS" ${ARGN} ) set(_NAME "absl_${ABSL_CC_TEST_NAME}") add_executable(${_NAME} "") target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS}) target_include_directories(${_NAME} PUBLIC ${ABSL_COMMON_INCLUDE_DIRS} PRIVATE ${absl_gtest_src_dir}/googletest/include ${absl_gtest_src_dir}/googlemock/include ) if (${ABSL_BUILD_DLL}) target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_TEST_DEFINES} ABSL_CONSUME_DLL ABSL_CONSUME_TEST_DLL GTEST_LINKED_AS_SHARED_LIBRARY=1 ) # Replace dependencies on targets inside the DLL with abseil_dll itself. absl_internal_dll_targets( DEPS ${ABSL_CC_TEST_DEPS} OUTPUT ABSL_CC_TEST_DEPS ) absl_internal_dll_targets( DEPS ${ABSL_CC_TEST_LINKOPTS} OUTPUT ABSL_CC_TEST_LINKOPTS ) else() target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_TEST_DEFINES} ) endif() target_compile_options(${_NAME} PRIVATE ${ABSL_CC_TEST_COPTS} ) target_link_libraries(${_NAME} PUBLIC ${ABSL_CC_TEST_DEPS} PRIVATE ${ABSL_CC_TEST_LINKOPTS} ) # Add all Abseil targets to a folder in the IDE for organization. set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test) if(ABSL_PROPAGATE_CXX_STD) # Abseil libraries require C++14 as the current minimum standard. # Top-level application CMake projects should ensure a consistent C++ # standard for all compiled sources by setting CMAKE_CXX_STANDARD. target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE}) endif() add_test(NAME ${_NAME} COMMAND ${_NAME}) endfunction() abseil-20240722.0/CMake/Googletest/000077500000000000000000000000001465274712700164665ustar00rootroot00000000000000abseil-20240722.0/CMake/Googletest/CMakeLists.txt.in000066400000000000000000000005721465274712700216370ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.16) project(googletest-external NONE) include(ExternalProject) ExternalProject_Add(googletest URL "${absl_gtest_download_url}" # May be empty SOURCE_DIR "${absl_gtest_src_dir}" BINARY_DIR "${absl_gtest_build_dir}" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" ) abseil-20240722.0/CMake/Googletest/DownloadGTest.cmake000066400000000000000000000031601465274712700222060ustar00rootroot00000000000000# Integrates googletest at configure time. Based on the instructions at # https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project # Set up the external googletest project, downloading the latest from Github # master if requested. configure_file( ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in ${CMAKE_BINARY_DIR}/googletest-external/CMakeLists.txt ) set(ABSL_SAVE_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) set(ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) if (BUILD_SHARED_LIBS) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_CREATE_SHARED_LIBRARY=1") endif() # Configure and build the googletest source. execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . RESULT_VARIABLE result WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external ) if(result) message(FATAL_ERROR "CMake step for googletest failed: ${result}") endif() execute_process(COMMAND ${CMAKE_COMMAND} --build . RESULT_VARIABLE result WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external) if(result) message(FATAL_ERROR "Build step for googletest failed: ${result}") endif() set(CMAKE_CXX_FLAGS ${ABSL_SAVE_CMAKE_CXX_FLAGS}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY}) # Prevent overriding the parent project's compiler/linker settings on Windows set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # Add googletest directly to our build. This defines the gtest and gtest_main # targets. add_subdirectory(${absl_gtest_src_dir} ${absl_gtest_build_dir} EXCLUDE_FROM_ALL) abseil-20240722.0/CMake/README.md000066400000000000000000000157271465274712700156450ustar00rootroot00000000000000# Abseil CMake Build Instructions Abseil comes with a CMake build script ([CMakeLists.txt](../CMakeLists.txt)) that can be used on a wide range of platforms ("C" stands for cross-platform.). If you don't have CMake installed already, you can download it for free from . CMake works by generating native makefiles or build projects that can be used in the compiler environment of your choice. For API/ABI compatibility reasons, we strongly recommend building Abseil in a subdirectory of your project or as an embedded dependency. ## Incorporating Abseil Into a CMake Project The recommendations below are similar to those for using CMake within the googletest framework () ### Step-by-Step Instructions 1. If you want to build the Abseil tests, integrate the Abseil dependency [Google Test](https://github.com/google/googletest) into your CMake project. To disable Abseil tests, you have to pass either `-DBUILD_TESTING=OFF` or `-DABSL_BUILD_TESTING=OFF` when configuring your project with CMake. 2. Download Abseil and copy it into a subdirectory in your CMake project or add Abseil as a [git submodule](https://git-scm.com/docs/git-submodule) in your CMake project. 3. You can then use the CMake command [`add_subdirectory()`](https://cmake.org/cmake/help/latest/command/add_subdirectory.html) to include Abseil directly in your CMake project. 4. Add the **absl::** target you wish to use to the [`target_link_libraries()`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html) section of your executable or of your library.
Here is a short CMakeLists.txt example of an application project using Abseil. ```cmake cmake_minimum_required(VERSION 3.16) project(my_app_project) # Pick the C++ standard to compile with. # Abseil currently supports C++14, C++17, and C++20. set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_subdirectory(abseil-cpp) add_executable(my_exe source.cpp) target_link_libraries(my_exe absl::base absl::synchronization absl::strings) ``` Note that if you are developing a library designed for use by other clients, you should instead leave `CMAKE_CXX_STANDARD` unset (or only set if being built as the current top-level CMake project) and configure the minimum required C++ standard at the target level. If you require a later minimum C++ standard than Abseil does, it's a good idea to also enforce that `CMAKE_CXX_STANDARD` (which will control Abseil library targets) is set to at least that minimum. For example: ```cmake cmake_minimum_required(VERSION 3.16) project(my_lib_project) # Leave C++ standard up to the root application, so set it only if this is the # current top-level CMake project. if(CMAKE_SOURCE_DIR STREQUAL my_lib_project_SOURCE_DIR) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() add_subdirectory(abseil-cpp) add_library(my_lib source.cpp) target_link_libraries(my_lib absl::base absl::synchronization absl::strings) # Enforce that my_lib requires C++17. Important to document for clients that they # must set CMAKE_CXX_STANDARD to 17 or higher for proper Abseil ABI compatibility # (since otherwise, Abseil library targets could be compiled with a lower C++ # standard than my_lib). target_compile_features(my_lib PUBLIC cxx_std_17) if(CMAKE_CXX_STANDARD LESS 17) message(FATAL_ERROR "my_lib_project requires CMAKE_CXX_STANDARD >= 17 (got: ${CMAKE_CXX_STANDARD})") endif() ``` Then the top-level application project that uses your library is responsible for setting a consistent `CMAKE_CXX_STANDARD` that is sufficiently high. ### Running Abseil Tests with CMake Use the `-DABSL_BUILD_TESTING=ON` flag to run Abseil tests. Note that BUILD_TESTING must also be on (the default). You will need to provide Abseil with a Googletest dependency. There are two options for how to do this: * Use `-DABSL_USE_GOOGLETEST_HEAD`. This will automatically download the latest Googletest source into the build directory at configure time. Googletest will then be compiled directly alongside Abseil's tests. * Manually integrate Googletest with your build. See https://github.com/google/googletest/blob/master/googletest/README.md#using-cmake for more information on using Googletest in a CMake project. For example, to run just the Abseil tests, you could use this script: ``` cd path/to/abseil-cpp mkdir build cd build cmake -DABSL_BUILD_TESTING=ON -DABSL_USE_GOOGLETEST_HEAD=ON .. make -j ctest ``` Currently, we only run our tests with CMake in a Linux environment, but we are working on the rest of our supported platforms. See https://github.com/abseil/abseil-cpp/projects/1 and https://github.com/abseil/abseil-cpp/issues/109 for more information. ### Available Abseil CMake Public Targets Here's a non-exhaustive list of Abseil CMake public targets: ```cmake absl::algorithm absl::base absl::debugging absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::random_random absl::strings absl::synchronization absl::time absl::utility ``` ## Traditional CMake Set-Up For larger projects, it may make sense to use the traditional CMake set-up where you build and install projects separately. First, you'd need to build and install Google Test: ``` cmake -S /source/googletest -B /build/googletest -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/installation/dir -DBUILD_GMOCK=ON cmake --build /build/googletest --target install ``` Then you need to configure and build Abseil. Make sure you enable `ABSL_USE_EXTERNAL_GOOGLETEST` and `ABSL_FIND_GOOGLETEST`. You also need to enable `ABSL_ENABLE_INSTALL` so that you can install Abseil itself. ``` cmake -S /source/abseil-cpp -B /build/abseil-cpp -DCMAKE_PREFIX_PATH=/installation/dir -DCMAKE_INSTALL_PREFIX=/installation/dir -DABSL_ENABLE_INSTALL=ON -DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON cmake --build /temporary/build/abseil-cpp ``` (`CMAKE_PREFIX_PATH` is where you already have Google Test installed; `CMAKE_INSTALL_PREFIX` is where you want to have Abseil installed; they can be different.) Run the tests: ``` ctest --test-dir /temporary/build/abseil-cpp ``` And finally install: ``` cmake --build /temporary/build/abseil-cpp --target install ``` # CMake Option Synopsis ## Enable Standard CMake Installation `-DABSL_ENABLE_INSTALL=ON` ## Google Test Options `-DABSL_BUILD_TESTING=ON` must be set to enable testing - Have Abseil download and build Google Test for you: `-DABSL_USE_EXTERNAL_GOOGLETEST=OFF` (default) - Download and build latest Google Test: `-DABSL_USE_GOOGLETEST_HEAD=ON` - Download specific Google Test version (ZIP archive): `-DABSL_GOOGLETEST_DOWNLOAD_URL=https://.../version.zip` - Use Google Test from specific local directory: `-DABSL_LOCAL_GOOGLETEST_DIR=/path/to/googletest` - Use Google Test included elsewhere in your project: `-DABSL_USE_EXTERNAL_GOOGLETEST=ON` - Use standard CMake `find_package(CTest)` to find installed Google Test: `-DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON` abseil-20240722.0/CMake/abslConfig.cmake.in000066400000000000000000000002601465274712700200260ustar00rootroot00000000000000# absl CMake configuration file. include(CMakeFindDependencyMacro) find_dependency(Threads) @PACKAGE_INIT@ include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") abseil-20240722.0/CMake/install_test_project/000077500000000000000000000000001465274712700206055ustar00rootroot00000000000000abseil-20240722.0/CMake/install_test_project/CMakeLists.txt000066400000000000000000000015021465274712700233430ustar00rootroot00000000000000# # 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. # A simple CMakeLists.txt for testing cmake installation cmake_minimum_required(VERSION 3.16) project(absl_cmake_testing CXX) add_executable(simple simple.cc) find_package(absl REQUIRED) target_link_libraries(simple absl::strings absl::config) abseil-20240722.0/CMake/install_test_project/simple.cc000066400000000000000000000021311465274712700224020ustar00rootroot00000000000000// // 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. #include #include "absl/base/config.h" #include "absl/strings/substitute.h" #if !defined(ABSL_LTS_RELEASE_VERSION) || ABSL_LTS_RELEASE_VERSION != 99998877 #error ABSL_LTS_RELEASE_VERSION is not set correctly. #endif #if !defined(ABSL_LTS_RELEASE_PATCH_LEVEL) || ABSL_LTS_RELEASE_PATCH_LEVEL != 0 #error ABSL_LTS_RELEASE_PATCH_LEVEL is not set correctly. #endif int main(int argc, char** argv) { for (int i = 0; i < argc; ++i) { std::cout << absl::Substitute("Arg $0: $1\n", i, argv[i]); } } abseil-20240722.0/CMake/install_test_project/test.sh000077500000000000000000000057271465274712700221360ustar00rootroot00000000000000#!/bin/bash # # 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. # # Unit and integration tests for Abseil LTS CMake installation # Fail on any error. Treat unset variables an error. Print commands as executed. set -euox pipefail absl_dir=/abseil-cpp absl_build_dir=/buildfs googletest_builddir=/googletest_builddir googletest_archive="googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz" project_dir="${absl_dir}/CMake/install_test_project" project_build_dir=/buildfs/project-build build_shared_libs="OFF" if [ "${LINK_TYPE:-}" = "DYNAMIC" ]; then build_shared_libs="ON" fi # Build and install GoogleTest mkdir "${googletest_builddir}" pushd "${googletest_builddir}" curl -L "${ABSL_GOOGLETEST_DOWNLOAD_URL}" --output "${googletest_archive}" tar -xz -f "${googletest_archive}" pushd "googletest-${ABSL_GOOGLETEST_VERSION}" mkdir build pushd build cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS="${build_shared_libs}" .. make -j $(nproc) make install ldconfig popd popd popd # Run the LTS transformations ./create_lts.py 99998877 # Build and install Abseil pushd "${absl_build_dir}" cmake "${absl_dir}" \ -DABSL_USE_EXTERNAL_GOOGLETEST=ON \ -DABSL_FIND_GOOGLETEST=ON \ -DCMAKE_BUILD_TYPE=Release \ -DABSL_BUILD_TESTING=ON \ -DBUILD_SHARED_LIBS="${build_shared_libs}" make -j $(nproc) ctest -j $(nproc) --output-on-failure make install ldconfig popd # Test the project against the installed Abseil mkdir -p "${project_build_dir}" pushd "${project_build_dir}" cmake "${project_dir}" cmake --build . --target simple output="$(${project_build_dir}/simple "printme" 2>&1)" if [[ "${output}" != *"Arg 1: printme"* ]]; then echo "Faulty output on simple project:" echo "${output}" exit 1 fi popd if ! grep absl::strings "/usr/local/lib/cmake/absl/abslTargets.cmake"; then cat "/usr/local/lib/cmake/absl/abslTargets.cmake" echo "CMake targets named incorrectly" exit 1 fi pushd "${HOME}" cat > hello-abseil.cc << EOF #include #include "absl/strings/str_format.h" int main(int argc, char **argv) { absl::PrintF("Hello Abseil!\n"); return EXIT_SUCCESS; } EOF if [ "${LINK_TYPE:-}" != "DYNAMIC" ]; then pc_args=($(pkg-config --cflags --libs --static absl_str_format)) g++ -static -o hello-abseil hello-abseil.cc "${pc_args[@]}" else pc_args=($(pkg-config --cflags --libs absl_str_format)) g++ -o hello-abseil hello-abseil.cc "${pc_args[@]}" fi hello="$(./hello-abseil)" [[ "${hello}" == "Hello Abseil!" ]] popd echo "Install test complete!" exit 0 abseil-20240722.0/CMakeLists.txt000066400000000000000000000217341465274712700161410ustar00rootroot00000000000000# # Copyright 2017 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. # # https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md # As of 2024-07-01, CMake 3.16 is the minimum supported version. cmake_minimum_required(VERSION 3.16) # Allow the user to specify the CMAKE_MSVC_DEBUG_INFORMATION_FORMAT if (POLICY CMP0141) cmake_policy(SET CMP0141 NEW) endif (POLICY CMP0141) project(absl LANGUAGES CXX VERSION 20240722) set(ABSL_SOVERSION "2407.0.0") include(CTest) # Output directory is correct by default for most build setups. However, when # building Abseil as a DLL, it is important to have the DLL in the same # directory as the executable using it. Thus, we put all executables in a single # /bin directory. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp)) # in the source tree of a project that uses it, install rules are disabled. if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) option(ABSL_ENABLE_INSTALL "Enable install rule" OFF) else() option(ABSL_ENABLE_INSTALL "Enable install rule" ON) endif() set(CMAKE_INSTALL_RPATH "$ORIGIN") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) option(ABSL_PROPAGATE_CXX_STD "Use CMake C++ standard meta features (e.g. cxx_std_14) that propagate to targets that link to Abseil" OFF) # TODO: Default to ON for CMake 3.8 and greater. if(NOT ABSL_PROPAGATE_CXX_STD) message(WARNING "A future Abseil release will default ABSL_PROPAGATE_CXX_STD to ON for CMake 3.8 and up. We recommend enabling this option to ensure your project still builds correctly.") endif() option(ABSL_USE_SYSTEM_INCLUDES "Silence warnings in Abseil headers by marking them as SYSTEM includes" OFF) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/CMake ${CMAKE_CURRENT_LIST_DIR}/absl/copts ) option(ABSL_MSVC_STATIC_RUNTIME "Link static runtime libraries" OFF) if(ABSL_MSVC_STATIC_RUNTIME) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") else() set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") endif() include(CMakePackageConfigHelpers) include(GNUInstallDirs) include(AbseilDll) include(AbseilHelpers) ## ## Using absl targets ## ## all public absl targets are ## exported with the absl:: prefix ## ## e.g absl::base absl::synchronization absl::strings .... ## ## DO NOT rely on the internal targets outside of the prefix # include current path list(APPEND ABSL_COMMON_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(ABSL_USING_CLANG ON) else() set(ABSL_USING_CLANG OFF) endif() # find dependencies ## pthread find_package(Threads REQUIRED) include(CMakeDependentOption) option(ABSL_BUILD_TESTING "If ON, Abseil will build all of Abseil's own tests." OFF) option(ABSL_BUILD_TEST_HELPERS "If ON, Abseil will build libraries that you can use to write tests against Abseil code. This option requires that Abseil is configured to use GoogleTest." OFF) option(ABSL_USE_EXTERNAL_GOOGLETEST "If ON, Abseil will assume that the targets for GoogleTest are already provided by the including project. This makes sense when Abseil is used with add_subdirectory." OFF) cmake_dependent_option(ABSL_FIND_GOOGLETEST "If ON, Abseil will use find_package(GTest) rather than assuming that GoogleTest is already provided by the including project." ON "ABSL_USE_EXTERNAL_GOOGLETEST" OFF) option(ABSL_USE_GOOGLETEST_HEAD "If ON, abseil will download HEAD from GoogleTest at config time." OFF) set(ABSL_GOOGLETEST_DOWNLOAD_URL "" CACHE STRING "If set, download GoogleTest from this URL") set(ABSL_LOCAL_GOOGLETEST_DIR "/usr/src/googletest" CACHE PATH "If ABSL_USE_GOOGLETEST_HEAD is OFF and ABSL_GOOGLETEST_URL is not set, specifies the directory of a local GoogleTest checkout." ) option(ABSL_BUILD_MONOLITHIC_SHARED_LIBS "Build Abseil as a single shared library (always enabled for Windows)" OFF ) if(NOT BUILD_SHARED_LIBS AND ABSL_BUILD_MONOLITHIC_SHARED_LIBS) message(WARNING "Not building a shared library because BUILD_SHARED_LIBS is not set. Ignoring ABSL_BUILD_MONOLITHIC_SHARED_LIBS.") endif() if((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS) if (ABSL_USE_EXTERNAL_GOOGLETEST) if (ABSL_FIND_GOOGLETEST) find_package(GTest REQUIRED) elseif(NOT TARGET GTest::gtest) if(TARGET gtest) # When Google Test is included directly rather than through find_package, the aliases are missing. add_library(GTest::gtest ALIAS gtest) add_library(GTest::gtest_main ALIAS gtest_main) add_library(GTest::gmock ALIAS gmock) add_library(GTest::gmock_main ALIAS gmock_main) else() message(FATAL_ERROR "ABSL_USE_EXTERNAL_GOOGLETEST is ON and ABSL_FIND_GOOGLETEST is OFF, which means that the top-level project must build the Google Test project. However, the target gtest was not found.") endif() endif() else() set(absl_gtest_build_dir ${CMAKE_BINARY_DIR}/googletest-build) if(ABSL_USE_GOOGLETEST_HEAD AND ABSL_GOOGLETEST_DOWNLOAD_URL) message(FATAL_ERROR "Do not set both ABSL_USE_GOOGLETEST_HEAD and ABSL_GOOGLETEST_DOWNLOAD_URL") endif() if(ABSL_USE_GOOGLETEST_HEAD) set(absl_gtest_download_url "https://github.com/google/googletest/archive/main.zip") elseif(ABSL_GOOGLETEST_DOWNLOAD_URL) set(absl_gtest_download_url ${ABSL_GOOGLETEST_DOWNLOAD_URL}) endif() if(absl_gtest_download_url) set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src) else() set(absl_gtest_src_dir ${ABSL_LOCAL_GOOGLETEST_DIR}) endif() include(CMake/Googletest/DownloadGTest.cmake) endif() endif() add_subdirectory(absl) if(ABSL_ENABLE_INSTALL) # install as a subdirectory only install(EXPORT ${PROJECT_NAME}Targets NAMESPACE absl:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) configure_package_config_file( CMake/abslConfig.cmake.in "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) # 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) write_basic_package_version_file( "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" COMPATIBILITY ExactVersion ) install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) endif() # absl_VERSION install(DIRECTORY absl DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.inc" PATTERN "*.h" PATTERN "copts" EXCLUDE PATTERN "testdata" EXCLUDE ) # Rewrite options.h to use the compiled ABI. file(READ "absl/base/options.h" ABSL_INTERNAL_OPTIONS_H_CONTENTS) # Handle features that require at least C++20. if (ABSL_INTERNAL_AT_LEAST_CXX20) foreach(FEATURE "ORDERING") string(REPLACE "#define ABSL_OPTION_USE_STD_${FEATURE} 2" "#define ABSL_OPTION_USE_STD_${FEATURE} 1" ABSL_INTERNAL_OPTIONS_H_PINNED "${ABSL_INTERNAL_OPTIONS_H_CONTENTS}") set(ABSL_INTERNAL_OPTIONS_H_CONTENTS "${ABSL_INTERNAL_OPTIONS_H_PINNED}") endforeach() endif() # Handle features that require at least C++17. if (ABSL_INTERNAL_AT_LEAST_CXX17) foreach(FEATURE "ANY" "OPTIONAL" "STRING_VIEW" "VARIANT") string(REPLACE "#define ABSL_OPTION_USE_STD_${FEATURE} 2" "#define ABSL_OPTION_USE_STD_${FEATURE} 1" ABSL_INTERNAL_OPTIONS_H_PINNED "${ABSL_INTERNAL_OPTIONS_H_CONTENTS}") set(ABSL_INTERNAL_OPTIONS_H_CONTENTS "${ABSL_INTERNAL_OPTIONS_H_PINNED}") endforeach() endif() # Any feature that still has the value of 2 (because it was not handled above) # should be set to 0. string(REGEX REPLACE "#define ABSL_OPTION_USE_STD_([^ ]*) 2" "#define ABSL_OPTION_USE_STD_\\1 0" ABSL_INTERNAL_OPTIONS_H_PINNED "${ABSL_INTERNAL_OPTIONS_H_CONTENTS}") file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/options-pinned.h" CONTENT "${ABSL_INTERNAL_OPTIONS_H_PINNED}") install(FILES "${CMAKE_BINARY_DIR}/options-pinned.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/absl/base RENAME "options.h") endif() # ABSL_ENABLE_INSTALL abseil-20240722.0/CONTRIBUTING.md000066400000000000000000000153301465274712700156250ustar00rootroot00000000000000# How to Contribute to Abseil We'd love to accept your patches and contributions to this project. There are just a few small guidelines you need to follow. NOTE: If you are new to GitHub, please start by reading [Pull Request howto](https://help.github.com/articles/about-pull-requests/) ## Contributor License Agreement Contributions to this project must be accompanied by a Contributor License Agreement. You (or your employer) retain the copyright to your contribution, this simply gives us permission to use and redistribute your contributions as part of the project. Head over to to see your current agreements on file or to sign a new one. You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again. ## Contribution Guidelines Potential contributors sometimes ask us if the Abseil project is the appropriate home for their utility library code or for specific functions implementing missing portions of the standard. Often, the answer to this question is "no". We’d like to articulate our thinking on this issue so that our choices can be understood by everyone and so that contributors can have a better intuition about whether Abseil might be interested in adopting a new library. ### Priorities Although our mission is to augment the C++ standard library, our goal is not to provide a full forward-compatible implementation of the latest standard. For us to consider a library for inclusion in Abseil, it is not enough that a library is useful. We generally choose to release a library when it meets at least one of the following criteria: * **Widespread usage** - Using our internal codebase to help gauge usage, most of the libraries we've released have tens of thousands of users. * **Anticipated widespread usage** - Pre-adoption of some standard-compliant APIs may not have broad adoption initially but can be expected to pick up usage when it replaces legacy APIs. `absl::from_chars`, for example, replaces existing code that converts strings to numbers and will therefore likely see usage growth. * **High impact** - APIs that provide a key solution to a specific problem, such as `absl::FixedArray`, have higher impact than usage numbers may signal and are released because of their importance. * **Direct support for a library that falls under one of the above** - When we want access to a smaller library as an implementation detail for a higher-priority library we plan to release, we may release it, as we did with portions of `absl/meta/type_traits.h`. One consequence of this is that the presence of a library in Abseil does not necessarily mean that other similar libraries would be a high priority. ### API Freeze Consequences Via the [Abseil Compatibility Guidelines](https://abseil.io/about/compatibility), we have promised a large degree of API stability. In particular, we will not make backward-incompatible changes to released APIs without also shipping a tool or process that can upgrade our users' code. We are not yet at the point of easily releasing such tools. Therefore, at this time, shipping a library establishes an API contract which is borderline unchangeable. (We can add new functionality, but we cannot easily change existing behavior.) This constraint forces us to very carefully review all APIs that we ship. ## Coding Style To keep the source consistent, readable, diffable and easy to merge, we use a fairly rigid coding style, as defined by the [google-styleguide](https://github.com/google/styleguide) project. All patches will be expected to conform to the style outlined [here](https://google.github.io/styleguide/cppguide.html). ## Guidelines for Pull Requests * If you are a Googler, it is required that you send us a Piper CL instead of using the GitHub pull-request process. The code propagation process will deliver the change to GitHub. * Create **small PRs** that are narrowly focused on **addressing a single concern**. We often receive PRs that are trying to fix several things at a time, but if only one fix is considered acceptable, nothing gets merged and both author's & review's time is wasted. Create more PRs to address different concerns and everyone will be happy. * For speculative changes, consider opening an [Abseil issue](https://github.com/abseil/abseil-cpp/issues) and discussing it first. If you are suggesting a behavioral or API change, consider starting with an [Abseil proposal template](ABSEIL_ISSUE_TEMPLATE.md). * Provide a good **PR description** as a record of **what** change is being made and **why** it was made. Link to a GitHub issue if it exists. * Don't fix code style and formatting unless you are already changing that line to address an issue. Formatting of modified lines may be done using `git clang-format`. PRs with irrelevant changes won't be merged. If you do want to fix formatting or style, do that in a separate PR. * Unless your PR is trivial, you should expect there will be reviewer comments that you'll need to address before merging. We expect you to be reasonably responsive to those comments, otherwise the PR will be closed after 2-3 weeks of inactivity. * Maintain **clean commit history** and use **meaningful commit messages**. PRs with messy commit history are difficult to review and won't be merged. Use `rebase -i upstream/master` to curate your commit history and/or to bring in latest changes from master (but avoid rebasing in the middle of a code review). * Keep your PR up to date with upstream/master (if there are merge conflicts, we can't really merge your change). * **All tests need to be passing** before your change can be merged. We recommend you **run tests locally** (see below) * Exceptions to the rules can be made if there's a compelling reason for doing so. That is - the rules are here to serve us, not the other way around, and the rules need to be serving their intended purpose to be valuable. * All submissions, including submissions by project members, require review. ## Running Tests If you have [Bazel](https://bazel.build/) installed, use `bazel test --test_tag_filters="-benchmark" ...` to run the unit tests. If you are running the Linux operating system and have [Docker](https://www.docker.com/) installed, you can also run the `linux_*.sh` scripts under the `ci/`(https://github.com/abseil/abseil-cpp/tree/master/ci) directory to test Abseil under a variety of conditions. ## Abseil Committers The current members of the Abseil engineering team are the only committers at present. ## Release Process Abseil lives at head, where latest-and-greatest code can be found. abseil-20240722.0/FAQ.md000066400000000000000000000215121465274712700143240ustar00rootroot00000000000000# Abseil FAQ ## Is Abseil the right home for my utility library? Most often the answer to the question is "no." As both the [About Abseil](https://abseil.io/about/) page and our [contributing guidelines](https://github.com/abseil/abseil-cpp/blob/master/CONTRIBUTING.md#contribution-guidelines) explain, Abseil contains a variety of core C++ library code that is widely used at [Google](https://www.google.com/). As such, Abseil's primary purpose is to be used as a dependency by Google's open source C++ projects. While we do hope that Abseil is also useful to the C++ community at large, this added constraint also means that we are unlikely to accept a contribution of utility code that isn't already widely used by Google. ## How to I set the C++ dialect used to build Abseil? The short answer is that whatever mechanism you choose, you need to make sure that you set this option consistently at the global level for your entire project. If, for example, you want to set the C++ dialect to C++17, with [Bazel](https://bazel/build/) as the build system and `gcc` or `clang` as the compiler, there several ways to do this: * Pass `--cxxopt=-std=c++17` on the command line (for example, `bazel build --cxxopt=-std=c++17 ...`) * Set the environment variable `BAZEL_CXXOPTS` (for example, `BAZEL_CXXOPTS=-std=c++17`) * Add `build --cxxopt=-std=c++17` to your [`.bazelrc` file](https://docs.bazel.build/versions/master/guide.html#bazelrc) If you are using CMake as the build system, you'll need to add a line like `set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. If you are developing a library designed to be used by other clients, you should instead leave `CMAKE_CXX_STANDARD` unset and configure the minimum C++ standard required by each of your library targets via `target_compile_features`. See the [CMake build instructions](https://github.com/abseil/abseil-cpp/blob/master/CMake/README.md) for more information. For a longer answer to this question and to understand why some other approaches don't work, see the answer to ["What is ABI and why don't you recommend using a pre-compiled version of Abseil?"](#what-is-abi-and-why-dont-you-recommend-using-a-pre-compiled-version-of-abseil) ## What is ABI and why don't you recommend using a pre-compiled version of Abseil? For the purposes of this discussion, you can think of [ABI](https://en.wikipedia.org/wiki/Application_binary_interface) as the compiled representation of the interfaces in code. This is in contrast to [API](https://en.wikipedia.org/wiki/Application_programming_interface), which you can think of as the interfaces as defined by the code itself. [Abseil has a strong promise of API compatibility, but does not make any promise of ABI compatibility](https://abseil.io/about/compatibility). Let's take a look at what this means in practice. You might be tempted to do something like this in a [Bazel](https://bazel.build/) `BUILD` file: ``` # DON'T DO THIS!!! cc_library( name = "my_library", srcs = ["my_library.cc"], copts = ["-std=c++17"], # May create a mixed-mode compile! deps = ["@com_google_absl//absl/strings"], ) ``` Applying `-std=c++17` to an individual target in your `BUILD` file is going to compile that specific target in C++17 mode, but it isn't going to ensure the Abseil library is built in C++17 mode, since the Abseil library itself is a different build target. If your code includes an Abseil header, then your program may contain conflicting definitions of the same class/function/variable/enum, etc. As a rule, all compile options that affect the ABI of a program need to be applied to the entire build on a global basis. C++ has something called the [One Definition Rule](https://en.wikipedia.org/wiki/One_Definition_Rule) (ODR). C++ doesn't allow multiple definitions of the same class/function/variable/enum, etc. ODR violations sometimes result in linker errors, but linkers do not always catch violations. Uncaught ODR violations can result in strange runtime behaviors or crashes that can be hard to debug. If you build the Abseil library and your code using different compile options that affect ABI, there is a good chance you will run afoul of the One Definition Rule. Examples of GCC compile options that affect ABI include (but aren't limited to) language dialect (e.g. `-std=`), optimization level (e.g. `-O2`), code generation flags (e.g. `-fexceptions`), and preprocessor defines (e.g. `-DNDEBUG`). If you use a pre-compiled version of Abseil, (for example, from your Linux distribution package manager or from something like [vcpkg](https://github.com/microsoft/vcpkg)) you have to be very careful to ensure ABI compatibility across the components of your program. The only way you can be sure your program is going to be correct regarding ABI is to ensure you've used the exact same compile options as were used to build the pre-compiled library. This does not mean that Abseil cannot work as part of a Linux distribution since a knowledgeable binary packager will have ensured that all packages have been built with consistent compile options. This is one of the reasons we warn against - though do not outright reject - using Abseil as a pre-compiled library. Another possible way that you might afoul of ABI issues is if you accidentally include two versions of Abseil in your program. Multiple versions of Abseil can end up within the same binary if your program uses the Abseil library and another library also transitively depends on Abseil (resulting in what is sometimes called the diamond dependency problem). In cases such as this you must structure your build so that all libraries use the same version of Abseil. [Abseil's strong promise of API compatibility between releases](https://abseil.io/about/compatibility) means the latest "HEAD" release of Abseil is almost certainly the right choice if you are doing as we recommend and building all of your code from source. For these reasons we recommend you avoid pre-compiled code and build the Abseil library yourself in a consistent manner with the rest of your code. ## What is "live at head" and how do I do it? From Abseil's point-of-view, "live at head" means that every Abseil source release (which happens on an almost daily basis) is either API compatible with the previous release, or comes with an automated tool that you can run over code to make it compatible. In practice, the need to use an automated tool is extremely rare. This means that upgrading from one source release to another should be a routine practice that can and should be performed often. We recommend you update to the [latest commit in the `master` branch of Abseil](https://github.com/abseil/abseil-cpp/commits/master) as often as possible. Not only will you pick up bug fixes more quickly, but if you have good automated testing, you will catch and be able to fix any [Hyrum's Law](https://www.hyrumslaw.com/) dependency problems on an incremental basis instead of being overwhelmed by them and having difficulty isolating them if you wait longer between updates. If you are using the [Bazel](https://bazel.build/) build system and its [external dependencies](https://docs.bazel.build/versions/master/external.html) feature, updating the [`http_archive`](https://docs.bazel.build/versions/master/repo/http.html#http_archive) rule in your [`WORKSPACE`](https://docs.bazel.build/versions/master/be/workspace.html) for `com_google_abseil` to point to the [latest commit in the `master` branch of Abseil](https://github.com/abseil/abseil-cpp/commits/master) is all you need to do. For example, on February 11, 2020, the latest commit to the master branch was `98eb410c93ad059f9bba1bf43f5bb916fc92a5ea`. To update to this commit, you would add the following snippet to your `WORKSPACE` file: ``` http_archive( name = "com_google_absl", urls = ["https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip"], # 2020-02-11T18:50:53Z strip_prefix = "abseil-cpp-98eb410c93ad059f9bba1bf43f5bb916fc92a5ea", sha256 = "aabf6c57e3834f8dc3873a927f37eaf69975d4b28117fc7427dfb1c661542a87", ) ``` To get the `sha256` of this URL, run `curl -sL --output - https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip | sha256sum -`. You can commit the updated `WORKSPACE` file to your source control every time you update, and if you have good automated testing, you might even consider automating this. One thing we don't recommend is using GitHub's `master.zip` files (for example [https://github.com/abseil/abseil-cpp/archive/master.zip](https://github.com/abseil/abseil-cpp/archive/master.zip)), which are always the latest commit in the `master` branch, to implement live at head. Since these `master.zip` URLs are not versioned, you will lose build reproducibility. In addition, some build systems, including Bazel, will simply cache this file, which means you won't actually be updating to the latest release until your cache is cleared or invalidated. abseil-20240722.0/LICENSE000066400000000000000000000261411465274712700144030ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. abseil-20240722.0/MODULE.bazel000066400000000000000000000025471465274712700154060ustar00rootroot00000000000000# Copyright 2024 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. # https://bazel.build/external/overview#bzlmod module( name = "abseil-cpp", version = "20240722.0", compatibility_level = 1, ) cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension") use_repo(cc_configure, "local_config_cc") # Only direct dependencies need to be listed below. # Please keep the versions in sync with the versions in the WORKSPACE file. bazel_dep(name = "bazel_skylib", version = "1.5.0") bazel_dep(name = "google_benchmark", version = "1.8.3", repo_name = "com_github_google_benchmark", dev_dependency = True) bazel_dep(name = "googletest", version = "1.15.2", repo_name = "com_google_googletest") bazel_dep(name = "platforms", version = "0.0.10") abseil-20240722.0/PrivacyInfo.xcprivacy000066400000000000000000000005751465274712700175640ustar00rootroot00000000000000 NSPrivacyTracking NSPrivacyCollectedDataTypes NSPrivacyTrackingDomains NSPrivacyAccessedAPITypes abseil-20240722.0/README.md000066400000000000000000000151341465274712700146550ustar00rootroot00000000000000# Abseil - C++ Common Libraries The repository contains the Abseil C++ library code. Abseil is an open-source collection of C++ code (compliant to C++14) designed to augment the C++ standard library. ## Table of Contents - [About Abseil](#about) - [Quickstart](#quickstart) - [Building Abseil](#build) - [Support](#support) - [Codemap](#codemap) - [Releases](#releases) - [License](#license) - [Links](#links) ## About Abseil Abseil is an open-source collection of C++ library code designed to augment the C++ standard library. The Abseil library code is collected from Google's own C++ code base, has been extensively tested and used in production, and is the same code we depend on in our daily coding lives. In some cases, Abseil provides pieces missing from the C++ standard; in others, Abseil provides alternatives to the standard for special needs we've found through usage in the Google code base. We denote those cases clearly within the library code we provide you. Abseil is not meant to be a competitor to the standard library; we've just found that many of these utilities serve a purpose within our code base, and we now want to provide those resources to the C++ community as a whole. ## Quickstart If you want to just get started, make sure you at least run through the [Abseil Quickstart](https://abseil.io/docs/cpp/quickstart). The Quickstart contains information about setting up your development environment, downloading the Abseil code, running tests, and getting a simple binary working. ## Building Abseil [Bazel](https://bazel.build) and [CMake](https://cmake.org/) are the official build systems for Abseil. See the [quickstart](https://abseil.io/docs/cpp/quickstart) for more information on building Abseil using the Bazel build system. If you require CMake support, please check the [CMake build instructions](CMake/README.md) and [CMake Quickstart](https://abseil.io/docs/cpp/quickstart-cmake). ## Support Abseil follows Google's [Foundational C++ Support Policy](https://opensource.google/documentation/policies/cplusplus-support). See [this table](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md) for a list of currently supported versions compilers, platforms, and build tools. ## Codemap Abseil contains the following C++ library components: * [`base`](absl/base/)
The `base` library contains initialization code and other code which all other Abseil code depends on. Code within `base` may not depend on any other code (other than the C++ standard library). * [`algorithm`](absl/algorithm/)
The `algorithm` library contains additions to the C++ `` library and container-based versions of such algorithms. * [`cleanup`](absl/cleanup/)
The `cleanup` library contains the control-flow-construct-like type `absl::Cleanup` which is used for executing a callback on scope exit. * [`container`](absl/container/)
The `container` library contains additional STL-style containers, including Abseil's unordered "Swiss table" containers. * [`crc`](absl/crc/) The `crc` library contains code for computing error-detecting cyclic redundancy checks on data. * [`debugging`](absl/debugging/)
The `debugging` library contains code useful for enabling leak checks, and stacktrace and symbolization utilities. * [`flags`](absl/flags/)
The `flags` library contains code for handling command line flags for libraries and binaries built with Abseil. * [`hash`](absl/hash/)
The `hash` library contains the hashing framework and default hash functor implementations for hashable types in Abseil. * [`log`](absl/log/)
The `log` library contains `LOG` and `CHECK` macros and facilities for writing logged messages out to disk, `stderr`, or user-extensible destinations. * [`memory`](absl/memory/)
The `memory` library contains memory management facilities that augment C++'s `` library. * [`meta`](absl/meta/)
The `meta` library contains compatible versions of type checks available within C++14 and C++17 versions of the C++ `` library. * [`numeric`](absl/numeric/)
The `numeric` library contains 128-bit integer types as well as implementations of C++20's bitwise math functions. * [`profiling`](absl/profiling/)
The `profiling` library contains utility code for profiling C++ entities. It is currently a private dependency of other Abseil libraries. * [`random`](absl/random/)
The `random` library contains functions for generating psuedorandom values. * [`status`](absl/status/)
The `status` library contains abstractions for error handling, specifically `absl::Status` and `absl::StatusOr`. * [`strings`](absl/strings/)
The `strings` library contains a variety of strings routines and utilities, including a C++14-compatible version of the C++17 `std::string_view` type. * [`synchronization`](absl/synchronization/)
The `synchronization` library contains concurrency primitives (Abseil's `absl::Mutex` class, an alternative to `std::mutex`) and a variety of synchronization abstractions. * [`time`](absl/time/)
The `time` library contains abstractions for computing with absolute points in time, durations of time, and formatting and parsing time within time zones. * [`types`](absl/types/)
The `types` library contains non-container utility types, like a C++14-compatible version of the C++17 `std::optional` type. * [`utility`](absl/utility/)
The `utility` library contains utility and helper code. ## Releases Abseil recommends users "live-at-head" (update to the latest commit from the master branch as often as possible). However, we realize this philosophy doesn't work for every project, so we also provide [Long Term Support Releases](https://github.com/abseil/abseil-cpp/releases) to which we backport fixes for severe bugs. See our [release management](https://abseil.io/about/releases) document for more details. ## License The Abseil C++ library is licensed under the terms of the Apache license. See [LICENSE](LICENSE) for more information. ## Links For more information about Abseil: * Consult our [Abseil Introduction](https://abseil.io/about/intro) * Read [Why Adopt Abseil](https://abseil.io/about/philosophy) to understand our design philosophy. * Peruse our [Abseil Compatibility Guarantees](https://abseil.io/about/compatibility) to understand both what we promise to you, and what we expect of you in return. abseil-20240722.0/UPGRADES.md000066400000000000000000000012011465274712700151200ustar00rootroot00000000000000# C++ Upgrade Tools Abseil may occasionally release API-breaking changes. As noted in our [Compatibility Guidelines][compatibility-guide], we will aim to provide a tool to do the work of effecting such API-breaking changes, when absolutely necessary. These tools will be listed on the [C++ Upgrade Tools][upgrade-tools] guide on https://abseil.io. For more information, the [C++ Automated Upgrade Guide][api-upgrades-guide] outlines this process. [compatibility-guide]: https://abseil.io/about/compatibility [api-upgrades-guide]: https://abseil.io/docs/cpp/tools/api-upgrades [upgrade-tools]: https://abseil.io/docs/cpp/tools/upgrades/ abseil-20240722.0/WORKSPACE000066400000000000000000000046111465274712700146550ustar00rootroot00000000000000# # 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. # workspace(name = "com_google_absl") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # GoogleTest/GoogleMock framework. Used by most unit-tests. http_archive( name = "com_google_googletest", sha256 = "7b42b4d6ed48810c5362c265a17faebe90dc2373c885e5216439d37927f02926", strip_prefix = "googletest-1.15.2", # Keep this URL in sync with the version in ci/cmake_common.sh and # ci/windows_msvc_cmake.bat. urls = ["https://github.com/google/googletest/releases/download/v1.15.2/googletest-1.15.2.tar.gz"], ) # RE2 (the regular expression library used by GoogleTest) http_archive( name = "com_googlesource_code_re2", sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b", strip_prefix = "re2-2024-07-02", urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"], repo_mapping = {"@abseil-cpp": "@com_google_absl"}, ) # Google benchmark. http_archive( name = "com_github_google_benchmark", sha256 = "6bc180a57d23d4d9515519f92b0c83d61b05b5bab188961f36ac7b06b0d9e9ce", strip_prefix = "benchmark-1.8.3", urls = ["https://github.com/google/benchmark/archive/refs/tags/v1.8.3.tar.gz"], ) # Bazel Skylib. http_archive( name = "bazel_skylib", sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94", urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"], ) # Bazel platform rules. http_archive( name = "platforms", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz", "https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz", ], sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee", ) abseil-20240722.0/WORKSPACE.bzlmod000066400000000000000000000015231465274712700161420ustar00rootroot00000000000000# Copyright 2024 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. # https://bazel.build/external/migration#workspace.bzlmod # # This file is intentionally empty. When bzlmod is enabled and this # file exists, the contents of WORKSPACE is ignored. This prevents # bzlmod builds from unintentionally depending on the WORKSPACE file. abseil-20240722.0/absl/000077500000000000000000000000001465274712700143135ustar00rootroot00000000000000abseil-20240722.0/absl/BUILD.bazel000066400000000000000000000061441465274712700161760ustar00rootroot00000000000000# # Copyright 2017 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. # load("@bazel_skylib//lib:selects.bzl", "selects") package(default_visibility = ["//visibility:public"]) licenses(["notice"]) config_setting( name = "clang_compiler", flag_values = { "@bazel_tools//tools/cpp:compiler": "clang", }, visibility = [":__subpackages__"], ) config_setting( name = "gcc_compiler", flag_values = { "@bazel_tools//tools/cpp:compiler": "gcc", }, visibility = [":__subpackages__"], ) config_setting( name = "mingw_unspecified_compiler", flag_values = { "@bazel_tools//tools/cpp:compiler": "mingw", }, visibility = [":__subpackages__"], ) config_setting( name = "mingw-gcc_compiler", flag_values = { "@bazel_tools//tools/cpp:compiler": "mingw-gcc", }, visibility = [":__subpackages__"], ) config_setting( name = "msvc_compiler", flag_values = { "@bazel_tools//tools/cpp:compiler": "msvc-cl", }, visibility = [":__subpackages__"], ) config_setting( name = "clang-cl_compiler", flag_values = { "@bazel_tools//tools/cpp:compiler": "clang-cl", }, visibility = [":__subpackages__"], ) config_setting( name = "osx", constraint_values = [ "@platforms//os:osx", ], ) config_setting( name = "ios", constraint_values = [ "@platforms//os:ios", ], ) config_setting( name = "ppc", values = { "cpu": "ppc", }, visibility = [":__subpackages__"], ) config_setting( name = "cpu_wasm", values = { "cpu": "wasm", }, visibility = [":__subpackages__"], ) config_setting( name = "cpu_wasm32", values = { "cpu": "wasm32", }, visibility = [":__subpackages__"], ) config_setting( name = "platforms_wasm32", constraint_values = [ "@platforms//cpu:wasm32", ], visibility = [":__subpackages__"], ) config_setting( name = "platforms_wasm64", constraint_values = [ "@platforms//cpu:wasm64", ], visibility = [":__subpackages__"], ) selects.config_setting_group( name = "wasm", match_any = [ ":cpu_wasm", ":cpu_wasm32", ":platforms_wasm32", ":platforms_wasm64", ], visibility = [":__subpackages__"], ) config_setting( name = "fuchsia", values = { "cpu": "fuchsia", }, visibility = [":__subpackages__"], ) selects.config_setting_group( name = "mingw_compiler", match_any = [ ":mingw_unspecified_compiler", ":mingw-gcc_compiler", ], visibility = [":__subpackages__"], ) abseil-20240722.0/absl/CMakeLists.txt000066400000000000000000000024051465274712700170540ustar00rootroot00000000000000# # Copyright 2017 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. # add_subdirectory(base) add_subdirectory(algorithm) add_subdirectory(cleanup) add_subdirectory(container) add_subdirectory(crc) add_subdirectory(debugging) add_subdirectory(flags) add_subdirectory(functional) add_subdirectory(hash) add_subdirectory(log) add_subdirectory(memory) add_subdirectory(meta) add_subdirectory(numeric) add_subdirectory(profiling) add_subdirectory(random) add_subdirectory(status) add_subdirectory(strings) add_subdirectory(synchronization) add_subdirectory(time) add_subdirectory(types) add_subdirectory(utility) if (ABSL_BUILD_DLL) absl_make_dll() if ((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS) absl_make_dll(TEST ON) endif() endif() abseil-20240722.0/absl/abseil.podspec.gen.py000077500000000000000000000171001465274712700203320ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- """This script generates abseil.podspec from all BUILD.bazel files. This is expected to run on abseil git repository with Bazel 1.0 on Linux. It recursively analyzes BUILD.bazel files using query command of Bazel to dump its build rules in XML format. From these rules, it constructs podspec structure. """ import argparse import collections import os import re import subprocess import xml.etree.ElementTree # Template of root podspec. SPEC_TEMPLATE = """ # This file has been automatically generated from a script. # Please make modifications to `abseil.podspec.gen.py` instead. Pod::Spec.new do |s| s.name = 'abseil' s.version = '${version}' s.summary = 'Abseil Common Libraries (C++) from Google' s.homepage = 'https://abseil.io' s.license = 'Apache License, Version 2.0' s.authors = { 'Abseil Team' => 'abseil-io@googlegroups.com' } s.source = { :git => 'https://github.com/abseil/abseil-cpp.git', :tag => '${tag}', } s.resource_bundles = { s.module_name => 'PrivacyInfo.xcprivacy', } s.module_name = 'absl' s.header_mappings_dir = 'absl' s.header_dir = 'absl' s.libraries = 'c++' s.compiler_flags = '-Wno-everything' s.pod_target_xcconfig = { 'USER_HEADER_SEARCH_PATHS' => '$(inherited) "$(PODS_TARGET_SRCROOT)"', 'USE_HEADERMAP' => 'NO', 'ALWAYS_SEARCH_USER_PATHS' => 'NO', } s.ios.deployment_target = '9.0' s.osx.deployment_target = '10.11' s.tvos.deployment_target = '9.0' s.watchos.deployment_target = '2.0' s.subspec 'xcprivacy' do |ss| ss.resource_bundles = { ss.module_name => 'PrivacyInfo.xcprivacy', } end """ # Rule object representing the rule of Bazel BUILD. Rule = collections.namedtuple( "Rule", "type name package srcs hdrs textual_hdrs deps visibility testonly") def get_elem_value(elem, name): """Returns the value of XML element with the given name.""" for child in elem: if child.attrib.get("name") != name: continue if child.tag == "string": return child.attrib.get("value") if child.tag == "boolean": return child.attrib.get("value") == "true" if child.tag == "list": return [nested_child.attrib.get("value") for nested_child in child] raise "Cannot recognize tag: " + child.tag return None def normalize_paths(paths): """Returns the list of normalized path.""" # e.g. ["//absl/strings:dir/header.h"] -> ["absl/strings/dir/header.h"] return [path.lstrip("/").replace(":", "/") for path in paths] def parse_rule(elem, package): """Returns a rule from bazel XML rule.""" return Rule( type=elem.attrib["class"], name=get_elem_value(elem, "name"), package=package, srcs=normalize_paths(get_elem_value(elem, "srcs") or []), hdrs=normalize_paths(get_elem_value(elem, "hdrs") or []), textual_hdrs=normalize_paths(get_elem_value(elem, "textual_hdrs") or []), deps=get_elem_value(elem, "deps") or [], visibility=get_elem_value(elem, "visibility") or [], testonly=get_elem_value(elem, "testonly") or False) def read_build(package): """Runs bazel query on given package file and returns all cc rules.""" result = subprocess.check_output( ["bazel", "query", package + ":all", "--output", "xml"]) root = xml.etree.ElementTree.fromstring(result) return [ parse_rule(elem, package) for elem in root if elem.tag == "rule" and elem.attrib["class"].startswith("cc_") ] def collect_rules(root_path): """Collects and returns all rules from root path recursively.""" rules = [] for cur, _, _ in os.walk(root_path): build_path = os.path.join(cur, "BUILD.bazel") if os.path.exists(build_path): rules.extend(read_build("//" + cur)) return rules def relevant_rule(rule): """Returns true if a given rule is relevant when generating a podspec.""" return ( # cc_library only (ignore cc_test, cc_binary) rule.type == "cc_library" and # ignore empty rule (rule.hdrs + rule.textual_hdrs + rule.srcs) and # ignore test-only rule not rule.testonly) def get_spec_var(depth): """Returns the name of variable for spec with given depth.""" return "s" if depth == 0 else "s{}".format(depth) def get_spec_name(label): """Converts the label of bazel rule to the name of podspec.""" assert label.startswith("//absl/"), "{} doesn't start with //absl/".format( label) # e.g. //absl/apple/banana -> abseil/apple/banana return "abseil/" + label[7:] def write_podspec(f, rules, args): """Writes a podspec from given rules and args.""" rule_dir = build_rule_directory(rules)["abseil"] # Write root part with given arguments spec = re.sub(r"\$\{(\w+)\}", lambda x: args[x.group(1)], SPEC_TEMPLATE).lstrip() f.write(spec) # Write all target rules write_podspec_map(f, rule_dir, 0) f.write("end\n") def build_rule_directory(rules): """Builds a tree-style rule directory from given rules.""" rule_dir = {} for rule in rules: cur = rule_dir for frag in get_spec_name(rule.package).split("/"): cur = cur.setdefault(frag, {}) cur[rule.name] = rule return rule_dir def write_podspec_map(f, cur_map, depth): """Writes podspec from rule map recursively.""" for key, value in sorted(cur_map.items()): indent = " " * (depth + 1) f.write("{indent}{var0}.subspec '{key}' do |{var1}|\n".format( indent=indent, key=key, var0=get_spec_var(depth), var1=get_spec_var(depth + 1))) if isinstance(value, dict): write_podspec_map(f, value, depth + 1) else: write_podspec_rule(f, value, depth + 1) f.write("{indent}end\n".format(indent=indent)) def write_podspec_rule(f, rule, depth): """Writes podspec from given rule.""" indent = " " * (depth + 1) spec_var = get_spec_var(depth) # Puts all files in hdrs, textual_hdrs, and srcs into source_files. # Since CocoaPods treats header_files a bit differently from bazel, # this won't generate a header_files field so that all source_files # are considered as header files. srcs = sorted(set(rule.hdrs + rule.textual_hdrs + rule.srcs)) write_indented_list( f, "{indent}{var}.source_files = ".format(indent=indent, var=spec_var), srcs) # Writes dependencies of this rule. for dep in sorted(rule.deps): name = get_spec_name(dep.replace(":", "/")) f.write("{indent}{var}.dependency '{dep}'\n".format( indent=indent, var=spec_var, dep=name)) # Writes dependency to xcprivacy f.write( "{indent}{var}.dependency '{dep}'\n".format( indent=indent, var=spec_var, dep="abseil/xcprivacy" ) ) def write_indented_list(f, leading, values): """Writes leading values in an indented style.""" f.write(leading) f.write((",\n" + " " * len(leading)).join("'{}'".format(v) for v in values)) f.write("\n") def generate(args): """Generates a podspec file from all BUILD files under absl directory.""" rules = filter(relevant_rule, collect_rules("absl")) with open(args.output, "wt") as f: write_podspec(f, rules, vars(args)) def main(): parser = argparse.ArgumentParser( description="Generates abseil.podspec from BUILD.bazel") parser.add_argument( "-v", "--version", help="The version of podspec", required=True) parser.add_argument( "-t", "--tag", default=None, help="The name of git tag (default: version)") parser.add_argument( "-o", "--output", default="abseil.podspec", help="The name of output file (default: abseil.podspec)") args = parser.parse_args() if args.tag is None: args.tag = args.version generate(args) if __name__ == "__main__": main() abseil-20240722.0/absl/algorithm/000077500000000000000000000000001465274712700163015ustar00rootroot00000000000000abseil-20240722.0/absl/algorithm/BUILD.bazel000066400000000000000000000041551465274712700201640ustar00rootroot00000000000000# # Copyright 2017 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. # load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", "ABSL_DEFAULT_LINKOPTS", "ABSL_TEST_COPTS", ) package( default_visibility = ["//visibility:public"], features = [ "header_modules", "layering_check", "parse_headers", ], ) licenses(["notice"]) cc_library( name = "algorithm", hdrs = ["algorithm.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ "//absl/base:config", ], ) cc_test( name = "algorithm_test", size = "small", srcs = ["algorithm_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":algorithm", "//absl/base:config", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "container", hdrs = [ "container.h", ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":algorithm", "//absl/base:config", "//absl/base:core_headers", "//absl/base:nullability", "//absl/meta:type_traits", ], ) cc_test( name = "container_test", srcs = ["container_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":container", "//absl/base", "//absl/base:config", "//absl/base:core_headers", "//absl/memory", "//absl/types:span", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) abseil-20240722.0/absl/algorithm/CMakeLists.txt000066400000000000000000000025271465274712700210470ustar00rootroot00000000000000# # Copyright 2017 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. # absl_cc_library( NAME algorithm HDRS "algorithm.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::config PUBLIC ) absl_cc_test( NAME algorithm_test SRCS "algorithm_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::algorithm absl::config GTest::gmock_main ) absl_cc_library( NAME algorithm_container HDRS "container.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::algorithm absl::config absl::core_headers absl::meta absl::nullability PUBLIC ) absl_cc_test( NAME container_test SRCS "container_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::algorithm_container absl::base absl::config absl::core_headers absl::memory absl::span GTest::gmock_main ) abseil-20240722.0/absl/algorithm/algorithm.h000066400000000000000000000042161465274712700204430ustar00rootroot00000000000000// Copyright 2017 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. // // ----------------------------------------------------------------------------- // File: algorithm.h // ----------------------------------------------------------------------------- // // This header file contains Google extensions to the standard C++ // header. #ifndef ABSL_ALGORITHM_ALGORITHM_H_ #define ABSL_ALGORITHM_ALGORITHM_H_ #include #include #include #include "absl/base/config.h" namespace absl { ABSL_NAMESPACE_BEGIN // equal() // rotate() // // Historical note: Abseil once provided implementations of these algorithms // prior to their adoption in C++14. New code should prefer to use the std // variants. // // See the documentation for the STL header for more information: // https://en.cppreference.com/w/cpp/header/algorithm using std::equal; using std::rotate; // linear_search() // // Performs a linear search for `value` using the iterator `first` up to // but not including `last`, returning true if [`first`, `last`) contains an // element equal to `value`. // // A linear search is of O(n) complexity which is guaranteed to make at most // n = (`last` - `first`) comparisons. A linear search over short containers // may be faster than a binary search, even when the container is sorted. template bool linear_search(InputIterator first, InputIterator last, const EqualityComparable& value) { return std::find(first, last, value) != last; } ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_ALGORITHM_ALGORITHM_H_ abseil-20240722.0/absl/algorithm/algorithm_test.cc000066400000000000000000000030051465274712700216330ustar00rootroot00000000000000// Copyright 2017 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 "absl/algorithm/algorithm.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/config.h" namespace { class LinearSearchTest : public testing::Test { protected: LinearSearchTest() : container_{1, 2, 3} {} static bool Is3(int n) { return n == 3; } static bool Is4(int n) { return n == 4; } std::vector container_; }; TEST_F(LinearSearchTest, linear_search) { EXPECT_TRUE(absl::linear_search(container_.begin(), container_.end(), 3)); EXPECT_FALSE(absl::linear_search(container_.begin(), container_.end(), 4)); } TEST_F(LinearSearchTest, linear_searchConst) { const std::vector *const const_container = &container_; EXPECT_TRUE( absl::linear_search(const_container->begin(), const_container->end(), 3)); EXPECT_FALSE( absl::linear_search(const_container->begin(), const_container->end(), 4)); } } // namespace abseil-20240722.0/absl/algorithm/container.h000066400000000000000000002342371465274712700204470ustar00rootroot00000000000000// Copyright 2017 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. // // ----------------------------------------------------------------------------- // File: container.h // ----------------------------------------------------------------------------- // // This header file provides Container-based versions of algorithmic functions // within the C++ standard library. The following standard library sets of // functions are covered within this file: // // * Algorithmic functions // * Algorithmic functions // * functions // // The standard library functions operate on iterator ranges; the functions // within this API operate on containers, though many return iterator ranges. // // All functions within this API are named with a `c_` prefix. Calls such as // `absl::c_xx(container, ...) are equivalent to std:: functions such as // `std::xx(std::begin(cont), std::end(cont), ...)`. Functions that act on // iterators but not conceptually on iterator ranges (e.g. `std::iter_swap`) // have no equivalent here. // // For template parameter and variable naming, `C` indicates the container type // to which the function is applied, `Pred` indicates the predicate object type // to be used by the function and `T` indicates the applicable element type. #ifndef ABSL_ALGORITHM_CONTAINER_H_ #define ABSL_ALGORITHM_CONTAINER_H_ #include #include #include #include #include #include #include #include #include #include #include "absl/algorithm/algorithm.h" #include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/base/nullability.h" #include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace container_algorithm_internal { // NOTE: it is important to defer to ADL lookup for building with C++ modules, // especially for headers like which are not visible from this file // but specialize std::begin and std::end. using std::begin; using std::end; // The type of the iterator given by begin(c) (possibly std::begin(c)). // ContainerIter> gives vector::const_iterator, // while ContainerIter> gives vector::iterator. template using ContainerIter = decltype(begin(std::declval())); // An MSVC bug involving template parameter substitution requires us to use // decltype() here instead of just std::pair. template using ContainerIterPairType = decltype(std::make_pair(ContainerIter(), ContainerIter())); template using ContainerDifferenceType = decltype(std::distance( std::declval>(), std::declval>())); template using ContainerPointerType = typename std::iterator_traits>::pointer; // container_algorithm_internal::c_begin and // container_algorithm_internal::c_end are abbreviations for proper ADL // lookup of std::begin and std::end, i.e. // using std::begin; // using std::end; // std::foo(begin(c), end(c)); // becomes // std::foo(container_algorithm_internal::c_begin(c), // container_algorithm_internal::c_end(c)); // These are meant for internal use only. template ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_begin(C& c) { return begin(c); } template ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_end(C& c) { return end(c); } template struct IsUnorderedContainer : std::false_type {}; template struct IsUnorderedContainer< std::unordered_map> : std::true_type {}; template struct IsUnorderedContainer> : std::true_type {}; } // namespace container_algorithm_internal // PUBLIC API //------------------------------------------------------------------------------ // Abseil algorithm.h functions //------------------------------------------------------------------------------ // c_linear_search() // // Container-based version of absl::linear_search() for performing a linear // search within a container. template bool c_linear_search(const C& c, EqualityComparable&& value) { return linear_search(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(value)); } //------------------------------------------------------------------------------ // algorithms //------------------------------------------------------------------------------ // c_distance() // // Container-based version of the `std::distance()` function to // return the number of elements within a container. template ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 container_algorithm_internal::ContainerDifferenceType c_distance(const C& c) { return std::distance(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } //------------------------------------------------------------------------------ // Non-modifying sequence operations //------------------------------------------------------------------------------ // c_all_of() // // Container-based version of the `std::all_of()` function to // test if all elements within a container satisfy a condition. template bool c_all_of(const C& c, Pred&& pred) { return std::all_of(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); } // c_any_of() // // Container-based version of the `std::any_of()` function to // test if any element in a container fulfills a condition. template bool c_any_of(const C& c, Pred&& pred) { return std::any_of(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); } // c_none_of() // // Container-based version of the `std::none_of()` function to // test if no elements in a container fulfill a condition. template bool c_none_of(const C& c, Pred&& pred) { return std::none_of(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); } // c_for_each() // // Container-based version of the `std::for_each()` function to // apply a function to a container's elements. template decay_t c_for_each(C&& c, Function&& f) { return std::for_each(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(f)); } // c_find() // // Container-based version of the `std::find()` function to find // the first element containing the passed value within a container value. template container_algorithm_internal::ContainerIter c_find(C& c, T&& value) { return std::find(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(value)); } // c_contains() // // Container-based version of the `std::ranges::contains()` C++23 // function to search a container for a value. template bool c_contains(const Sequence& sequence, T&& value) { return absl::c_find(sequence, std::forward(value)) != container_algorithm_internal::c_end(sequence); } // c_find_if() // // Container-based version of the `std::find_if()` function to find // the first element in a container matching the given condition. template container_algorithm_internal::ContainerIter c_find_if(C& c, Pred&& pred) { return std::find_if(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); } // c_find_if_not() // // Container-based version of the `std::find_if_not()` function to // find the first element in a container not matching the given condition. template container_algorithm_internal::ContainerIter c_find_if_not(C& c, Pred&& pred) { return std::find_if_not(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); } // c_find_end() // // Container-based version of the `std::find_end()` function to // find the last subsequence within a container. template container_algorithm_internal::ContainerIter c_find_end( Sequence1& sequence, Sequence2& subsequence) { return std::find_end(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), container_algorithm_internal::c_end(subsequence)); } // Overload of c_find_end() for using a predicate evaluation other than `==` as // the function's test condition. template container_algorithm_internal::ContainerIter c_find_end( Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { return std::find_end(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), container_algorithm_internal::c_end(subsequence), std::forward(pred)); } // c_find_first_of() // // Container-based version of the `std::find_first_of()` function to // find the first element within the container that is also within the options // container. template container_algorithm_internal::ContainerIter c_find_first_of(C1& container, C2& options) { return std::find_first_of(container_algorithm_internal::c_begin(container), container_algorithm_internal::c_end(container), container_algorithm_internal::c_begin(options), container_algorithm_internal::c_end(options)); } // Overload of c_find_first_of() for using a predicate evaluation other than // `==` as the function's test condition. template container_algorithm_internal::ContainerIter c_find_first_of( C1& container, C2& options, BinaryPredicate&& pred) { return std::find_first_of(container_algorithm_internal::c_begin(container), container_algorithm_internal::c_end(container), container_algorithm_internal::c_begin(options), container_algorithm_internal::c_end(options), std::forward(pred)); } // c_adjacent_find() // // Container-based version of the `std::adjacent_find()` function to // find equal adjacent elements within a container. template container_algorithm_internal::ContainerIter c_adjacent_find( Sequence& sequence) { return std::adjacent_find(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } // Overload of c_adjacent_find() for using a predicate evaluation other than // `==` as the function's test condition. template container_algorithm_internal::ContainerIter c_adjacent_find( Sequence& sequence, BinaryPredicate&& pred) { return std::adjacent_find(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(pred)); } // c_count() // // Container-based version of the `std::count()` function to count // values that match within a container. template container_algorithm_internal::ContainerDifferenceType c_count( const C& c, T&& value) { return std::count(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(value)); } // c_count_if() // // Container-based version of the `std::count_if()` function to // count values matching a condition within a container. template container_algorithm_internal::ContainerDifferenceType c_count_if( const C& c, Pred&& pred) { return std::count_if(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); } // c_mismatch() // // Container-based version of the `std::mismatch()` function to // return the first element where two ordered containers differ. Applies `==` to // the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). template container_algorithm_internal::ContainerIterPairType c_mismatch(C1& c1, C2& c2) { return std::mismatch(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2)); } // Overload of c_mismatch() for using a predicate evaluation other than `==` as // the function's test condition. Applies `pred`to the first N elements of `c1` // and `c2`, where N = min(size(c1), size(c2)). template container_algorithm_internal::ContainerIterPairType c_mismatch( C1& c1, C2& c2, BinaryPredicate pred) { return std::mismatch(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), pred); } // c_equal() // // Container-based version of the `std::equal()` function to // test whether two containers are equal. template bool c_equal(const C1& c1, const C2& c2) { return std::equal(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2)); } // Overload of c_equal() for using a predicate evaluation other than `==` as // the function's test condition. template bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) { return std::equal(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), std::forward(pred)); } // c_is_permutation() // // Container-based version of the `std::is_permutation()` function // to test whether a container is a permutation of another. template bool c_is_permutation(const C1& c1, const C2& c2) { return std::is_permutation(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2)); } // Overload of c_is_permutation() for using a predicate evaluation other than // `==` as the function's test condition. template bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) { return std::is_permutation(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), std::forward(pred)); } // c_search() // // Container-based version of the `std::search()` function to search // a container for a subsequence. template container_algorithm_internal::ContainerIter c_search( Sequence1& sequence, Sequence2& subsequence) { return std::search(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), container_algorithm_internal::c_end(subsequence)); } // Overload of c_search() for using a predicate evaluation other than // `==` as the function's test condition. template container_algorithm_internal::ContainerIter c_search( Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { return std::search(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), container_algorithm_internal::c_end(subsequence), std::forward(pred)); } // c_contains_subrange() // // Container-based version of the `std::ranges::contains_subrange()` // C++23 function to search a container for a subsequence. template bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence) { return absl::c_search(sequence, subsequence) != container_algorithm_internal::c_end(sequence); } // Overload of c_contains_subrange() for using a predicate evaluation other than // `==` as the function's test condition. template bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { return absl::c_search(sequence, subsequence, std::forward(pred)) != container_algorithm_internal::c_end(sequence); } // c_search_n() // // Container-based version of the `std::search_n()` function to // search a container for the first sequence of N elements. template container_algorithm_internal::ContainerIter c_search_n( Sequence& sequence, Size count, T&& value) { return std::search_n(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), count, std::forward(value)); } // Overload of c_search_n() for using a predicate evaluation other than // `==` as the function's test condition. template container_algorithm_internal::ContainerIter c_search_n( Sequence& sequence, Size count, T&& value, BinaryPredicate&& pred) { return std::search_n(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), count, std::forward(value), std::forward(pred)); } //------------------------------------------------------------------------------ // Modifying sequence operations //------------------------------------------------------------------------------ // c_copy() // // Container-based version of the `std::copy()` function to copy a // container's elements into an iterator. template OutputIterator c_copy(const InputSequence& input, OutputIterator output) { return std::copy(container_algorithm_internal::c_begin(input), container_algorithm_internal::c_end(input), output); } // c_copy_n() // // Container-based version of the `std::copy_n()` function to copy a // container's first N elements into an iterator. template OutputIterator c_copy_n(const C& input, Size n, OutputIterator output) { return std::copy_n(container_algorithm_internal::c_begin(input), n, output); } // c_copy_if() // // Container-based version of the `std::copy_if()` function to copy // a container's elements satisfying some condition into an iterator. template OutputIterator c_copy_if(const InputSequence& input, OutputIterator output, Pred&& pred) { return std::copy_if(container_algorithm_internal::c_begin(input), container_algorithm_internal::c_end(input), output, std::forward(pred)); } // c_copy_backward() // // Container-based version of the `std::copy_backward()` function to // copy a container's elements in reverse order into an iterator. template BidirectionalIterator c_copy_backward(const C& src, BidirectionalIterator dest) { return std::copy_backward(container_algorithm_internal::c_begin(src), container_algorithm_internal::c_end(src), dest); } // c_move() // // Container-based version of the `std::move()` function to move // a container's elements into an iterator. template OutputIterator c_move(C&& src, OutputIterator dest) { return std::move(container_algorithm_internal::c_begin(src), container_algorithm_internal::c_end(src), dest); } // c_move_backward() // // Container-based version of the `std::move_backward()` function to // move a container's elements into an iterator in reverse order. template BidirectionalIterator c_move_backward(C&& src, BidirectionalIterator dest) { return std::move_backward(container_algorithm_internal::c_begin(src), container_algorithm_internal::c_end(src), dest); } // c_swap_ranges() // // Container-based version of the `std::swap_ranges()` function to // swap a container's elements with another container's elements. Swaps the // first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). template container_algorithm_internal::ContainerIter c_swap_ranges(C1& c1, C2& c2) { auto first1 = container_algorithm_internal::c_begin(c1); auto last1 = container_algorithm_internal::c_end(c1); auto first2 = container_algorithm_internal::c_begin(c2); auto last2 = container_algorithm_internal::c_end(c2); using std::swap; for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) { swap(*first1, *first2); } return first2; } // c_transform() // // Container-based version of the `std::transform()` function to // transform a container's elements using the unary operation, storing the // result in an iterator pointing to the last transformed element in the output // range. template OutputIterator c_transform(const InputSequence& input, OutputIterator output, UnaryOp&& unary_op) { return std::transform(container_algorithm_internal::c_begin(input), container_algorithm_internal::c_end(input), output, std::forward(unary_op)); } // Overload of c_transform() for performing a transformation using a binary // predicate. Applies `binary_op` to the first N elements of `c1` and `c2`, // where N = min(size(c1), size(c2)). template OutputIterator c_transform(const InputSequence1& input1, const InputSequence2& input2, OutputIterator output, BinaryOp&& binary_op) { auto first1 = container_algorithm_internal::c_begin(input1); auto last1 = container_algorithm_internal::c_end(input1); auto first2 = container_algorithm_internal::c_begin(input2); auto last2 = container_algorithm_internal::c_end(input2); for (; first1 != last1 && first2 != last2; ++first1, (void)++first2, ++output) { *output = binary_op(*first1, *first2); } return output; } // c_replace() // // Container-based version of the `std::replace()` function to // replace a container's elements of some value with a new value. The container // is modified in place. template void c_replace(Sequence& sequence, const T& old_value, const T& new_value) { std::replace(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), old_value, new_value); } // c_replace_if() // // Container-based version of the `std::replace_if()` function to // replace a container's elements of some value with a new value based on some // condition. The container is modified in place. template void c_replace_if(C& c, Pred&& pred, T&& new_value) { std::replace_if(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred), std::forward(new_value)); } // c_replace_copy() // // Container-based version of the `std::replace_copy()` function to // replace a container's elements of some value with a new value and return the // results within an iterator. template OutputIterator c_replace_copy(const C& c, OutputIterator result, T&& old_value, T&& new_value) { return std::replace_copy(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), result, std::forward(old_value), std::forward(new_value)); } // c_replace_copy_if() // // Container-based version of the `std::replace_copy_if()` function // to replace a container's elements of some value with a new value based on // some condition, and return the results within an iterator. template OutputIterator c_replace_copy_if(const C& c, OutputIterator result, Pred&& pred, const T& new_value) { return std::replace_copy_if(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), result, std::forward(pred), new_value); } // c_fill() // // Container-based version of the `std::fill()` function to fill a // container with some value. template void c_fill(C& c, const T& value) { std::fill(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), value); } // c_fill_n() // // Container-based version of the `std::fill_n()` function to fill // the first N elements in a container with some value. template void c_fill_n(C& c, Size n, const T& value) { std::fill_n(container_algorithm_internal::c_begin(c), n, value); } // c_generate() // // Container-based version of the `std::generate()` function to // assign a container's elements to the values provided by the given generator. template void c_generate(C& c, Generator&& gen) { std::generate(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(gen)); } // c_generate_n() // // Container-based version of the `std::generate_n()` function to // assign a container's first N elements to the values provided by the given // generator. template container_algorithm_internal::ContainerIter c_generate_n(C& c, Size n, Generator&& gen) { return std::generate_n(container_algorithm_internal::c_begin(c), n, std::forward(gen)); } // Note: `c_xx()` container versions for `remove()`, `remove_if()`, // and `unique()` are omitted, because it's not clear whether or not such // functions should call erase on their supplied sequences afterwards. Either // behavior would be surprising for a different set of users. // c_remove_copy() // // Container-based version of the `std::remove_copy()` function to // copy a container's elements while removing any elements matching the given // `value`. template OutputIterator c_remove_copy(const C& c, OutputIterator result, const T& value) { return std::remove_copy(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), result, value); } // c_remove_copy_if() // // Container-based version of the `std::remove_copy_if()` function // to copy a container's elements while removing any elements matching the given // condition. template OutputIterator c_remove_copy_if(const C& c, OutputIterator result, Pred&& pred) { return std::remove_copy_if(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), result, std::forward(pred)); } // c_unique_copy() // // Container-based version of the `std::unique_copy()` function to // copy a container's elements while removing any elements containing duplicate // values. template OutputIterator c_unique_copy(const C& c, OutputIterator result) { return std::unique_copy(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), result); } // Overload of c_unique_copy() for using a predicate evaluation other than // `==` for comparing uniqueness of the element values. template OutputIterator c_unique_copy(const C& c, OutputIterator result, BinaryPredicate&& pred) { return std::unique_copy(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), result, std::forward(pred)); } // c_reverse() // // Container-based version of the `std::reverse()` function to // reverse a container's elements. template void c_reverse(Sequence& sequence) { std::reverse(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } // c_reverse_copy() // // Container-based version of the `std::reverse()` function to // reverse a container's elements and write them to an iterator range. template OutputIterator c_reverse_copy(const C& sequence, OutputIterator result) { return std::reverse_copy(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), result); } // c_rotate() // // Container-based version of the `std::rotate()` function to // shift a container's elements leftward such that the `middle` element becomes // the first element in the container. template > Iterator c_rotate(C& sequence, Iterator middle) { return absl::rotate(container_algorithm_internal::c_begin(sequence), middle, container_algorithm_internal::c_end(sequence)); } // c_rotate_copy() // // Container-based version of the `std::rotate_copy()` function to // shift a container's elements leftward such that the `middle` element becomes // the first element in a new iterator range. template OutputIterator c_rotate_copy( const C& sequence, container_algorithm_internal::ContainerIter middle, OutputIterator result) { return std::rotate_copy(container_algorithm_internal::c_begin(sequence), middle, container_algorithm_internal::c_end(sequence), result); } // c_shuffle() // // Container-based version of the `std::shuffle()` function to // randomly shuffle elements within the container using a `gen()` uniform random // number generator. template void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) { std::shuffle(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(gen)); } // c_sample() // // Container-based version of the `std::sample()` function to // randomly sample elements from the container without replacement using a // `gen()` uniform random number generator and write them to an iterator range. template OutputIterator c_sample(const C& c, OutputIterator result, Distance n, UniformRandomBitGenerator&& gen) { #if defined(__cpp_lib_sample) && __cpp_lib_sample >= 201603L return std::sample(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), result, n, std::forward(gen)); #else // Fall back to a stable selection-sampling implementation. auto first = container_algorithm_internal::c_begin(c); Distance unsampled_elements = c_distance(c); n = (std::min)(n, unsampled_elements); for (; n != 0; ++first) { Distance r = std::uniform_int_distribution(0, --unsampled_elements)(gen); if (r < n) { *result++ = *first; --n; } } return result; #endif } //------------------------------------------------------------------------------ // Partition functions //------------------------------------------------------------------------------ // c_is_partitioned() // // Container-based version of the `std::is_partitioned()` function // to test whether all elements in the container for which `pred` returns `true` // precede those for which `pred` is `false`. template bool c_is_partitioned(const C& c, Pred&& pred) { return std::is_partitioned(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); } // c_partition() // // Container-based version of the `std::partition()` function // to rearrange all elements in a container in such a way that all elements for // which `pred` returns `true` precede all those for which it returns `false`, // returning an iterator to the first element of the second group. template container_algorithm_internal::ContainerIter c_partition(C& c, Pred&& pred) { return std::partition(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); } // c_stable_partition() // // Container-based version of the `std::stable_partition()` function // to rearrange all elements in a container in such a way that all elements for // which `pred` returns `true` precede all those for which it returns `false`, // preserving the relative ordering between the two groups. The function returns // an iterator to the first element of the second group. template container_algorithm_internal::ContainerIter c_stable_partition(C& c, Pred&& pred) { return std::stable_partition(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); } // c_partition_copy() // // Container-based version of the `std::partition_copy()` function // to partition a container's elements and return them into two iterators: one // for which `pred` returns `true`, and one for which `pred` returns `false.` template std::pair c_partition_copy( const C& c, OutputIterator1 out_true, OutputIterator2 out_false, Pred&& pred) { return std::partition_copy(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), out_true, out_false, std::forward(pred)); } // c_partition_point() // // Container-based version of the `std::partition_point()` function // to return the first element of an already partitioned container for which // the given `pred` is not `true`. template container_algorithm_internal::ContainerIter c_partition_point(C& c, Pred&& pred) { return std::partition_point(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); } //------------------------------------------------------------------------------ // Sorting functions //------------------------------------------------------------------------------ // c_sort() // // Container-based version of the `std::sort()` function // to sort elements in ascending order of their values. template void c_sort(C& c) { std::sort(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } // Overload of c_sort() for performing a `comp` comparison other than the // default `operator<`. template void c_sort(C& c, LessThan&& comp) { std::sort(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(comp)); } // c_stable_sort() // // Container-based version of the `std::stable_sort()` function // to sort elements in ascending order of their values, preserving the order // of equivalents. template void c_stable_sort(C& c) { std::stable_sort(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } // Overload of c_stable_sort() for performing a `comp` comparison other than the // default `operator<`. template void c_stable_sort(C& c, LessThan&& comp) { std::stable_sort(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(comp)); } // c_is_sorted() // // Container-based version of the `std::is_sorted()` function // to evaluate whether the given container is sorted in ascending order. template bool c_is_sorted(const C& c) { return std::is_sorted(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } // c_is_sorted() overload for performing a `comp` comparison other than the // default `operator<`. template bool c_is_sorted(const C& c, LessThan&& comp) { return std::is_sorted(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(comp)); } // c_partial_sort() // // Container-based version of the `std::partial_sort()` function // to rearrange elements within a container such that elements before `middle` // are sorted in ascending order. template void c_partial_sort( RandomAccessContainer& sequence, container_algorithm_internal::ContainerIter middle) { std::partial_sort(container_algorithm_internal::c_begin(sequence), middle, container_algorithm_internal::c_end(sequence)); } // Overload of c_partial_sort() for performing a `comp` comparison other than // the default `operator<`. template void c_partial_sort( RandomAccessContainer& sequence, container_algorithm_internal::ContainerIter middle, LessThan&& comp) { std::partial_sort(container_algorithm_internal::c_begin(sequence), middle, container_algorithm_internal::c_end(sequence), std::forward(comp)); } // c_partial_sort_copy() // // Container-based version of the `std::partial_sort_copy()` // function to sort the elements in the given range `result` within the larger // `sequence` in ascending order (and using `result` as the output parameter). // At most min(result.last - result.first, sequence.last - sequence.first) // elements from the sequence will be stored in the result. template container_algorithm_internal::ContainerIter c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) { return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(result), container_algorithm_internal::c_end(result)); } // Overload of c_partial_sort_copy() for performing a `comp` comparison other // than the default `operator<`. template container_algorithm_internal::ContainerIter c_partial_sort_copy(const C& sequence, RandomAccessContainer& result, LessThan&& comp) { return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(result), container_algorithm_internal::c_end(result), std::forward(comp)); } // c_is_sorted_until() // // Container-based version of the `std::is_sorted_until()` function // to return the first element within a container that is not sorted in // ascending order as an iterator. template container_algorithm_internal::ContainerIter c_is_sorted_until(C& c) { return std::is_sorted_until(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } // Overload of c_is_sorted_until() for performing a `comp` comparison other than // the default `operator<`. template container_algorithm_internal::ContainerIter c_is_sorted_until( C& c, LessThan&& comp) { return std::is_sorted_until(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(comp)); } // c_nth_element() // // Container-based version of the `std::nth_element()` function // to rearrange the elements within a container such that the `nth` element // would be in that position in an ordered sequence; other elements may be in // any order, except that all preceding `nth` will be less than that element, // and all following `nth` will be greater than that element. template void c_nth_element( RandomAccessContainer& sequence, container_algorithm_internal::ContainerIter nth) { std::nth_element(container_algorithm_internal::c_begin(sequence), nth, container_algorithm_internal::c_end(sequence)); } // Overload of c_nth_element() for performing a `comp` comparison other than // the default `operator<`. template void c_nth_element( RandomAccessContainer& sequence, container_algorithm_internal::ContainerIter nth, LessThan&& comp) { std::nth_element(container_algorithm_internal::c_begin(sequence), nth, container_algorithm_internal::c_end(sequence), std::forward(comp)); } //------------------------------------------------------------------------------ // Binary Search //------------------------------------------------------------------------------ // c_lower_bound() // // Container-based version of the `std::lower_bound()` function // to return an iterator pointing to the first element in a sorted container // which does not compare less than `value`. template container_algorithm_internal::ContainerIter c_lower_bound( Sequence& sequence, const T& value) { return std::lower_bound(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), value); } // Overload of c_lower_bound() for performing a `comp` comparison other than // the default `operator<`. template container_algorithm_internal::ContainerIter c_lower_bound( Sequence& sequence, const T& value, LessThan&& comp) { return std::lower_bound(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), value, std::forward(comp)); } // c_upper_bound() // // Container-based version of the `std::upper_bound()` function // to return an iterator pointing to the first element in a sorted container // which is greater than `value`. template container_algorithm_internal::ContainerIter c_upper_bound( Sequence& sequence, const T& value) { return std::upper_bound(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), value); } // Overload of c_upper_bound() for performing a `comp` comparison other than // the default `operator<`. template container_algorithm_internal::ContainerIter c_upper_bound( Sequence& sequence, const T& value, LessThan&& comp) { return std::upper_bound(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), value, std::forward(comp)); } // c_equal_range() // // Container-based version of the `std::equal_range()` function // to return an iterator pair pointing to the first and last elements in a // sorted container which compare equal to `value`. template container_algorithm_internal::ContainerIterPairType c_equal_range(Sequence& sequence, const T& value) { return std::equal_range(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), value); } // Overload of c_equal_range() for performing a `comp` comparison other than // the default `operator<`. template container_algorithm_internal::ContainerIterPairType c_equal_range(Sequence& sequence, const T& value, LessThan&& comp) { return std::equal_range(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), value, std::forward(comp)); } // c_binary_search() // // Container-based version of the `std::binary_search()` function // to test if any element in the sorted container contains a value equivalent to // 'value'. template bool c_binary_search(const Sequence& sequence, const T& value) { return std::binary_search(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), value); } // Overload of c_binary_search() for performing a `comp` comparison other than // the default `operator<`. template bool c_binary_search(const Sequence& sequence, const T& value, LessThan&& comp) { return std::binary_search(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), value, std::forward(comp)); } //------------------------------------------------------------------------------ // Merge functions //------------------------------------------------------------------------------ // c_merge() // // Container-based version of the `std::merge()` function // to merge two sorted containers into a single sorted iterator. template OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result) { return std::merge(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), result); } // Overload of c_merge() for performing a `comp` comparison other than // the default `operator<`. template OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result, LessThan&& comp) { return std::merge(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), result, std::forward(comp)); } // c_inplace_merge() // // Container-based version of the `std::inplace_merge()` function // to merge a supplied iterator `middle` into a container. template void c_inplace_merge(C& c, container_algorithm_internal::ContainerIter middle) { std::inplace_merge(container_algorithm_internal::c_begin(c), middle, container_algorithm_internal::c_end(c)); } // Overload of c_inplace_merge() for performing a merge using a `comp` other // than `operator<`. template void c_inplace_merge(C& c, container_algorithm_internal::ContainerIter middle, LessThan&& comp) { std::inplace_merge(container_algorithm_internal::c_begin(c), middle, container_algorithm_internal::c_end(c), std::forward(comp)); } // c_includes() // // Container-based version of the `std::includes()` function // to test whether a sorted container `c1` entirely contains another sorted // container `c2`. template bool c_includes(const C1& c1, const C2& c2) { return std::includes(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2)); } // Overload of c_includes() for performing a merge using a `comp` other than // `operator<`. template bool c_includes(const C1& c1, const C2& c2, LessThan&& comp) { return std::includes(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), std::forward(comp)); } // c_set_union() // // Container-based version of the `std::set_union()` function // to return an iterator containing the union of two containers; duplicate // values are not copied into the output. template ::value, void>::type, typename = typename std::enable_if< !container_algorithm_internal::IsUnorderedContainer::value, void>::type> OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) { return std::set_union(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), output); } // Overload of c_set_union() for performing a merge using a `comp` other than // `operator<`. template ::value, void>::type, typename = typename std::enable_if< !container_algorithm_internal::IsUnorderedContainer::value, void>::type> OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) { return std::set_union(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), output, std::forward(comp)); } // c_set_intersection() // // Container-based version of the `std::set_intersection()` function // to return an iterator containing the intersection of two sorted containers. template ::value, void>::type, typename = typename std::enable_if< !container_algorithm_internal::IsUnorderedContainer::value, void>::type> OutputIterator c_set_intersection(const C1& c1, const C2& c2, OutputIterator output) { // In debug builds, ensure that both containers are sorted with respect to the // default comparator. std::set_intersection requires the containers be sorted // using operator<. assert(absl::c_is_sorted(c1)); assert(absl::c_is_sorted(c2)); return std::set_intersection(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), output); } // Overload of c_set_intersection() for performing a merge using a `comp` other // than `operator<`. template ::value, void>::type, typename = typename std::enable_if< !container_algorithm_internal::IsUnorderedContainer::value, void>::type> OutputIterator c_set_intersection(const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) { // In debug builds, ensure that both containers are sorted with respect to the // default comparator. std::set_intersection requires the containers be sorted // using the same comparator. assert(absl::c_is_sorted(c1, comp)); assert(absl::c_is_sorted(c2, comp)); return std::set_intersection(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), output, std::forward(comp)); } // c_set_difference() // // Container-based version of the `std::set_difference()` function // to return an iterator containing elements present in the first container but // not in the second. template ::value, void>::type, typename = typename std::enable_if< !container_algorithm_internal::IsUnorderedContainer::value, void>::type> OutputIterator c_set_difference(const C1& c1, const C2& c2, OutputIterator output) { return std::set_difference(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), output); } // Overload of c_set_difference() for performing a merge using a `comp` other // than `operator<`. template ::value, void>::type, typename = typename std::enable_if< !container_algorithm_internal::IsUnorderedContainer::value, void>::type> OutputIterator c_set_difference(const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) { return std::set_difference(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), output, std::forward(comp)); } // c_set_symmetric_difference() // // Container-based version of the `std::set_symmetric_difference()` // function to return an iterator containing elements present in either one // container or the other, but not both. template ::value, void>::type, typename = typename std::enable_if< !container_algorithm_internal::IsUnorderedContainer::value, void>::type> OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, OutputIterator output) { return std::set_symmetric_difference( container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), output); } // Overload of c_set_symmetric_difference() for performing a merge using a // `comp` other than `operator<`. template ::value, void>::type, typename = typename std::enable_if< !container_algorithm_internal::IsUnorderedContainer::value, void>::type> OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, OutputIterator output, LessThan&& comp) { return std::set_symmetric_difference( container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), container_algorithm_internal::c_end(c2), output, std::forward(comp)); } //------------------------------------------------------------------------------ // Heap functions //------------------------------------------------------------------------------ // c_push_heap() // // Container-based version of the `std::push_heap()` function // to push a value onto a container heap. template void c_push_heap(RandomAccessContainer& sequence) { std::push_heap(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } // Overload of c_push_heap() for performing a push operation on a heap using a // `comp` other than `operator<`. template void c_push_heap(RandomAccessContainer& sequence, LessThan&& comp) { std::push_heap(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(comp)); } // c_pop_heap() // // Container-based version of the `std::pop_heap()` function // to pop a value from a heap container. template void c_pop_heap(RandomAccessContainer& sequence) { std::pop_heap(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } // Overload of c_pop_heap() for performing a pop operation on a heap using a // `comp` other than `operator<`. template void c_pop_heap(RandomAccessContainer& sequence, LessThan&& comp) { std::pop_heap(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(comp)); } // c_make_heap() // // Container-based version of the `std::make_heap()` function // to make a container a heap. template void c_make_heap(RandomAccessContainer& sequence) { std::make_heap(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } // Overload of c_make_heap() for performing heap comparisons using a // `comp` other than `operator<` template void c_make_heap(RandomAccessContainer& sequence, LessThan&& comp) { std::make_heap(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(comp)); } // c_sort_heap() // // Container-based version of the `std::sort_heap()` function // to sort a heap into ascending order (after which it is no longer a heap). template void c_sort_heap(RandomAccessContainer& sequence) { std::sort_heap(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } // Overload of c_sort_heap() for performing heap comparisons using a // `comp` other than `operator<` template void c_sort_heap(RandomAccessContainer& sequence, LessThan&& comp) { std::sort_heap(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(comp)); } // c_is_heap() // // Container-based version of the `std::is_heap()` function // to check whether the given container is a heap. template bool c_is_heap(const RandomAccessContainer& sequence) { return std::is_heap(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } // Overload of c_is_heap() for performing heap comparisons using a // `comp` other than `operator<` template bool c_is_heap(const RandomAccessContainer& sequence, LessThan&& comp) { return std::is_heap(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(comp)); } // c_is_heap_until() // // Container-based version of the `std::is_heap_until()` function // to find the first element in a given container which is not in heap order. template container_algorithm_internal::ContainerIter c_is_heap_until(RandomAccessContainer& sequence) { return std::is_heap_until(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } // Overload of c_is_heap_until() for performing heap comparisons using a // `comp` other than `operator<` template container_algorithm_internal::ContainerIter c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) { return std::is_heap_until(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(comp)); } //------------------------------------------------------------------------------ // Min/max //------------------------------------------------------------------------------ // c_min_element() // // Container-based version of the `std::min_element()` function // to return an iterator pointing to the element with the smallest value, using // `operator<` to make the comparisons. template ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 container_algorithm_internal::ContainerIter c_min_element(Sequence& sequence) { return std::min_element(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } // Overload of c_min_element() for performing a `comp` comparison other than // `operator<`. template ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 container_algorithm_internal::ContainerIter c_min_element(Sequence& sequence, LessThan&& comp) { return std::min_element(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(comp)); } // c_max_element() // // Container-based version of the `std::max_element()` function // to return an iterator pointing to the element with the largest value, using // `operator<` to make the comparisons. template ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 container_algorithm_internal::ContainerIter c_max_element(Sequence& sequence) { return std::max_element(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } // Overload of c_max_element() for performing a `comp` comparison other than // `operator<`. template ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 container_algorithm_internal::ContainerIter c_max_element(Sequence& sequence, LessThan&& comp) { return std::max_element(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(comp)); } // c_minmax_element() // // Container-based version of the `std::minmax_element()` function // to return a pair of iterators pointing to the elements containing the // smallest and largest values, respectively, using `operator<` to make the // comparisons. template ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 container_algorithm_internal::ContainerIterPairType c_minmax_element(C& c) { return std::minmax_element(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } // Overload of c_minmax_element() for performing `comp` comparisons other than // `operator<`. template ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 container_algorithm_internal::ContainerIterPairType c_minmax_element(C& c, LessThan&& comp) { return std::minmax_element(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(comp)); } //------------------------------------------------------------------------------ // Lexicographical Comparisons //------------------------------------------------------------------------------ // c_lexicographical_compare() // // Container-based version of the `std::lexicographical_compare()` // function to lexicographically compare (e.g. sort words alphabetically) two // container sequences. The comparison is performed using `operator<`. Note // that capital letters ("A-Z") have ASCII values less than lowercase letters // ("a-z"). template bool c_lexicographical_compare(const Sequence1& sequence1, const Sequence2& sequence2) { return std::lexicographical_compare( container_algorithm_internal::c_begin(sequence1), container_algorithm_internal::c_end(sequence1), container_algorithm_internal::c_begin(sequence2), container_algorithm_internal::c_end(sequence2)); } // Overload of c_lexicographical_compare() for performing a lexicographical // comparison using a `comp` operator instead of `operator<`. template bool c_lexicographical_compare(const Sequence1& sequence1, const Sequence2& sequence2, LessThan&& comp) { return std::lexicographical_compare( container_algorithm_internal::c_begin(sequence1), container_algorithm_internal::c_end(sequence1), container_algorithm_internal::c_begin(sequence2), container_algorithm_internal::c_end(sequence2), std::forward(comp)); } // c_next_permutation() // // Container-based version of the `std::next_permutation()` function // to rearrange a container's elements into the next lexicographically greater // permutation. template bool c_next_permutation(C& c) { return std::next_permutation(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } // Overload of c_next_permutation() for performing a lexicographical // comparison using a `comp` operator instead of `operator<`. template bool c_next_permutation(C& c, LessThan&& comp) { return std::next_permutation(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(comp)); } // c_prev_permutation() // // Container-based version of the `std::prev_permutation()` function // to rearrange a container's elements into the next lexicographically lesser // permutation. template bool c_prev_permutation(C& c) { return std::prev_permutation(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } // Overload of c_prev_permutation() for performing a lexicographical // comparison using a `comp` operator instead of `operator<`. template bool c_prev_permutation(C& c, LessThan&& comp) { return std::prev_permutation(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(comp)); } //------------------------------------------------------------------------------ // algorithms //------------------------------------------------------------------------------ // c_iota() // // Container-based version of the `std::iota()` function // to compute successive values of `value`, as if incremented with `++value` // after each element is written, and write them to the container. template void c_iota(Sequence& sequence, const T& value) { std::iota(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), value); } // c_accumulate() // // Container-based version of the `std::accumulate()` function // to accumulate the element values of a container to `init` and return that // accumulation by value. // // Note: Due to a language technicality this function has return type // absl::decay_t. As a user of this function you can casually read // this as "returns T by value" and assume it does the right thing. template decay_t c_accumulate(const Sequence& sequence, T&& init) { return std::accumulate(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(init)); } // Overload of c_accumulate() for using a binary operations other than // addition for computing the accumulation. template decay_t c_accumulate(const Sequence& sequence, T&& init, BinaryOp&& binary_op) { return std::accumulate(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(init), std::forward(binary_op)); } // c_inner_product() // // Container-based version of the `std::inner_product()` function // to compute the cumulative inner product of container element pairs. // // Note: Due to a language technicality this function has return type // absl::decay_t. As a user of this function you can casually read // this as "returns T by value" and assume it does the right thing. template decay_t c_inner_product(const Sequence1& factors1, const Sequence2& factors2, T&& sum) { return std::inner_product(container_algorithm_internal::c_begin(factors1), container_algorithm_internal::c_end(factors1), container_algorithm_internal::c_begin(factors2), std::forward(sum)); } // Overload of c_inner_product() for using binary operations other than // `operator+` (for computing the accumulation) and `operator*` (for computing // the product between the two container's element pair). template decay_t c_inner_product(const Sequence1& factors1, const Sequence2& factors2, T&& sum, BinaryOp1&& op1, BinaryOp2&& op2) { return std::inner_product(container_algorithm_internal::c_begin(factors1), container_algorithm_internal::c_end(factors1), container_algorithm_internal::c_begin(factors2), std::forward(sum), std::forward(op1), std::forward(op2)); } // c_adjacent_difference() // // Container-based version of the `std::adjacent_difference()` // function to compute the difference between each element and the one preceding // it and write it to an iterator. template OutputIt c_adjacent_difference(const InputSequence& input, OutputIt output_first) { return std::adjacent_difference(container_algorithm_internal::c_begin(input), container_algorithm_internal::c_end(input), output_first); } // Overload of c_adjacent_difference() for using a binary operation other than // subtraction to compute the adjacent difference. template OutputIt c_adjacent_difference(const InputSequence& input, OutputIt output_first, BinaryOp&& op) { return std::adjacent_difference(container_algorithm_internal::c_begin(input), container_algorithm_internal::c_end(input), output_first, std::forward(op)); } // c_partial_sum() // // Container-based version of the `std::partial_sum()` function // to compute the partial sum of the elements in a sequence and write them // to an iterator. The partial sum is the sum of all element values so far in // the sequence. template OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first) { return std::partial_sum(container_algorithm_internal::c_begin(input), container_algorithm_internal::c_end(input), output_first); } // Overload of c_partial_sum() for using a binary operation other than addition // to compute the "partial sum". template OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first, BinaryOp&& op) { return std::partial_sum(container_algorithm_internal::c_begin(input), container_algorithm_internal::c_end(input), output_first, std::forward(op)); } ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_ALGORITHM_CONTAINER_H_ abseil-20240722.0/absl/algorithm/container_test.cc000066400000000000000000001154211465274712700216350ustar00rootroot00000000000000// Copyright 2017 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 "absl/algorithm/container.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/casts.h" #include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/memory/memory.h" #include "absl/types/span.h" namespace { using ::testing::Each; using ::testing::ElementsAre; using ::testing::Gt; using ::testing::IsNull; using ::testing::IsSubsetOf; using ::testing::Lt; using ::testing::Pointee; using ::testing::SizeIs; using ::testing::Truly; using ::testing::UnorderedElementsAre; // Most of these tests just check that the code compiles, not that it // does the right thing. That's fine since the functions just forward // to the STL implementation. class NonMutatingTest : public testing::Test { protected: std::unordered_set container_ = {1, 2, 3}; std::list sequence_ = {1, 2, 3}; std::vector vector_ = {1, 2, 3}; int array_[3] = {1, 2, 3}; }; struct AccumulateCalls { void operator()(int value) { calls.push_back(value); } std::vector calls; }; bool Predicate(int value) { return value < 3; } bool BinPredicate(int v1, int v2) { return v1 < v2; } bool Equals(int v1, int v2) { return v1 == v2; } bool IsOdd(int x) { return x % 2 != 0; } TEST_F(NonMutatingTest, Distance) { EXPECT_EQ(container_.size(), static_cast(absl::c_distance(container_))); EXPECT_EQ(sequence_.size(), static_cast(absl::c_distance(sequence_))); EXPECT_EQ(vector_.size(), static_cast(absl::c_distance(vector_))); EXPECT_EQ(ABSL_ARRAYSIZE(array_), static_cast(absl::c_distance(array_))); // Works with a temporary argument. EXPECT_EQ(vector_.size(), static_cast(absl::c_distance(std::vector(vector_)))); } TEST_F(NonMutatingTest, Distance_OverloadedBeginEnd) { // Works with classes which have custom ADL-selected overloads of std::begin // and std::end. std::initializer_list a = {1, 2, 3}; std::valarray b = {1, 2, 3}; EXPECT_EQ(3, absl::c_distance(a)); EXPECT_EQ(3, absl::c_distance(b)); // It is assumed that other c_* functions use the same mechanism for // ADL-selecting begin/end overloads. } TEST_F(NonMutatingTest, ForEach) { AccumulateCalls c = absl::c_for_each(container_, AccumulateCalls()); // Don't rely on the unordered_set's order. std::sort(c.calls.begin(), c.calls.end()); EXPECT_EQ(vector_, c.calls); // Works with temporary container, too. AccumulateCalls c2 = absl::c_for_each(std::unordered_set(container_), AccumulateCalls()); std::sort(c2.calls.begin(), c2.calls.end()); EXPECT_EQ(vector_, c2.calls); } TEST_F(NonMutatingTest, FindReturnsCorrectType) { auto it = absl::c_find(container_, 3); EXPECT_EQ(3, *it); absl::c_find(absl::implicit_cast&>(sequence_), 3); } TEST_F(NonMutatingTest, Contains) { EXPECT_TRUE(absl::c_contains(container_, 3)); EXPECT_FALSE(absl::c_contains(container_, 4)); } TEST_F(NonMutatingTest, FindIf) { absl::c_find_if(container_, Predicate); } TEST_F(NonMutatingTest, FindIfNot) { absl::c_find_if_not(container_, Predicate); } TEST_F(NonMutatingTest, FindEnd) { absl::c_find_end(sequence_, vector_); absl::c_find_end(vector_, sequence_); } TEST_F(NonMutatingTest, FindEndWithPredicate) { absl::c_find_end(sequence_, vector_, BinPredicate); absl::c_find_end(vector_, sequence_, BinPredicate); } TEST_F(NonMutatingTest, FindFirstOf) { absl::c_find_first_of(container_, sequence_); absl::c_find_first_of(sequence_, container_); } TEST_F(NonMutatingTest, FindFirstOfWithPredicate) { absl::c_find_first_of(container_, sequence_, BinPredicate); absl::c_find_first_of(sequence_, container_, BinPredicate); } TEST_F(NonMutatingTest, AdjacentFind) { absl::c_adjacent_find(sequence_); } TEST_F(NonMutatingTest, AdjacentFindWithPredicate) { absl::c_adjacent_find(sequence_, BinPredicate); } TEST_F(NonMutatingTest, Count) { EXPECT_EQ(1, absl::c_count(container_, 3)); } TEST_F(NonMutatingTest, CountIf) { EXPECT_EQ(2, absl::c_count_if(container_, Predicate)); const std::unordered_set& const_container = container_; EXPECT_EQ(2, absl::c_count_if(const_container, Predicate)); } TEST_F(NonMutatingTest, Mismatch) { // Testing necessary as absl::c_mismatch executes logic. { auto result = absl::c_mismatch(vector_, sequence_); EXPECT_EQ(result.first, vector_.end()); EXPECT_EQ(result.second, sequence_.end()); } { auto result = absl::c_mismatch(sequence_, vector_); EXPECT_EQ(result.first, sequence_.end()); EXPECT_EQ(result.second, vector_.end()); } sequence_.back() = 5; { auto result = absl::c_mismatch(vector_, sequence_); EXPECT_EQ(result.first, std::prev(vector_.end())); EXPECT_EQ(result.second, std::prev(sequence_.end())); } { auto result = absl::c_mismatch(sequence_, vector_); EXPECT_EQ(result.first, std::prev(sequence_.end())); EXPECT_EQ(result.second, std::prev(vector_.end())); } sequence_.pop_back(); { auto result = absl::c_mismatch(vector_, sequence_); EXPECT_EQ(result.first, std::prev(vector_.end())); EXPECT_EQ(result.second, sequence_.end()); } { auto result = absl::c_mismatch(sequence_, vector_); EXPECT_EQ(result.first, sequence_.end()); EXPECT_EQ(result.second, std::prev(vector_.end())); } { struct NoNotEquals { constexpr bool operator==(NoNotEquals) const { return true; } constexpr bool operator!=(NoNotEquals) const = delete; }; std::vector first; std::list second; // Check this still compiles. absl::c_mismatch(first, second); } } TEST_F(NonMutatingTest, MismatchWithPredicate) { // Testing necessary as absl::c_mismatch executes logic. { auto result = absl::c_mismatch(vector_, sequence_, BinPredicate); EXPECT_EQ(result.first, vector_.begin()); EXPECT_EQ(result.second, sequence_.begin()); } { auto result = absl::c_mismatch(sequence_, vector_, BinPredicate); EXPECT_EQ(result.first, sequence_.begin()); EXPECT_EQ(result.second, vector_.begin()); } sequence_.front() = 0; { auto result = absl::c_mismatch(vector_, sequence_, BinPredicate); EXPECT_EQ(result.first, vector_.begin()); EXPECT_EQ(result.second, sequence_.begin()); } { auto result = absl::c_mismatch(sequence_, vector_, BinPredicate); EXPECT_EQ(result.first, std::next(sequence_.begin())); EXPECT_EQ(result.second, std::next(vector_.begin())); } sequence_.clear(); { auto result = absl::c_mismatch(vector_, sequence_, BinPredicate); EXPECT_EQ(result.first, vector_.begin()); EXPECT_EQ(result.second, sequence_.end()); } { auto result = absl::c_mismatch(sequence_, vector_, BinPredicate); EXPECT_EQ(result.first, sequence_.end()); EXPECT_EQ(result.second, vector_.begin()); } } TEST_F(NonMutatingTest, Equal) { EXPECT_TRUE(absl::c_equal(vector_, sequence_)); EXPECT_TRUE(absl::c_equal(sequence_, vector_)); EXPECT_TRUE(absl::c_equal(sequence_, array_)); EXPECT_TRUE(absl::c_equal(array_, vector_)); // Test that behavior appropriately differs from that of equal(). std::vector vector_plus = {1, 2, 3}; vector_plus.push_back(4); EXPECT_FALSE(absl::c_equal(vector_plus, sequence_)); EXPECT_FALSE(absl::c_equal(sequence_, vector_plus)); EXPECT_FALSE(absl::c_equal(array_, vector_plus)); } TEST_F(NonMutatingTest, EqualWithPredicate) { EXPECT_TRUE(absl::c_equal(vector_, sequence_, Equals)); EXPECT_TRUE(absl::c_equal(sequence_, vector_, Equals)); EXPECT_TRUE(absl::c_equal(array_, sequence_, Equals)); EXPECT_TRUE(absl::c_equal(vector_, array_, Equals)); // Test that behavior appropriately differs from that of equal(). std::vector vector_plus = {1, 2, 3}; vector_plus.push_back(4); EXPECT_FALSE(absl::c_equal(vector_plus, sequence_, Equals)); EXPECT_FALSE(absl::c_equal(sequence_, vector_plus, Equals)); EXPECT_FALSE(absl::c_equal(vector_plus, array_, Equals)); } TEST_F(NonMutatingTest, IsPermutation) { auto vector_permut_ = vector_; std::next_permutation(vector_permut_.begin(), vector_permut_.end()); EXPECT_TRUE(absl::c_is_permutation(vector_permut_, sequence_)); EXPECT_TRUE(absl::c_is_permutation(sequence_, vector_permut_)); // Test that behavior appropriately differs from that of is_permutation(). std::vector vector_plus = {1, 2, 3}; vector_plus.push_back(4); EXPECT_FALSE(absl::c_is_permutation(vector_plus, sequence_)); EXPECT_FALSE(absl::c_is_permutation(sequence_, vector_plus)); } TEST_F(NonMutatingTest, IsPermutationWithPredicate) { auto vector_permut_ = vector_; std::next_permutation(vector_permut_.begin(), vector_permut_.end()); EXPECT_TRUE(absl::c_is_permutation(vector_permut_, sequence_, Equals)); EXPECT_TRUE(absl::c_is_permutation(sequence_, vector_permut_, Equals)); // Test that behavior appropriately differs from that of is_permutation(). std::vector vector_plus = {1, 2, 3}; vector_plus.push_back(4); EXPECT_FALSE(absl::c_is_permutation(vector_plus, sequence_, Equals)); EXPECT_FALSE(absl::c_is_permutation(sequence_, vector_plus, Equals)); } TEST_F(NonMutatingTest, Search) { absl::c_search(sequence_, vector_); absl::c_search(vector_, sequence_); absl::c_search(array_, sequence_); } TEST_F(NonMutatingTest, SearchWithPredicate) { absl::c_search(sequence_, vector_, BinPredicate); absl::c_search(vector_, sequence_, BinPredicate); } TEST_F(NonMutatingTest, ContainsSubrange) { EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_)); EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_)); EXPECT_TRUE(absl::c_contains_subrange(array_, sequence_)); } TEST_F(NonMutatingTest, ContainsSubrangeWithPredicate) { EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_, Equals)); EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_, Equals)); } TEST_F(NonMutatingTest, SearchN) { absl::c_search_n(sequence_, 3, 1); } TEST_F(NonMutatingTest, SearchNWithPredicate) { absl::c_search_n(sequence_, 3, 1, BinPredicate); } TEST_F(NonMutatingTest, LowerBound) { std::list::iterator i = absl::c_lower_bound(sequence_, 3); ASSERT_TRUE(i != sequence_.end()); EXPECT_EQ(2, std::distance(sequence_.begin(), i)); EXPECT_EQ(3, *i); } TEST_F(NonMutatingTest, LowerBoundWithPredicate) { std::vector v(vector_); std::sort(v.begin(), v.end(), std::greater()); std::vector::iterator i = absl::c_lower_bound(v, 3, std::greater()); EXPECT_TRUE(i == v.begin()); EXPECT_EQ(3, *i); } TEST_F(NonMutatingTest, UpperBound) { std::list::iterator i = absl::c_upper_bound(sequence_, 1); ASSERT_TRUE(i != sequence_.end()); EXPECT_EQ(1, std::distance(sequence_.begin(), i)); EXPECT_EQ(2, *i); } TEST_F(NonMutatingTest, UpperBoundWithPredicate) { std::vector v(vector_); std::sort(v.begin(), v.end(), std::greater()); std::vector::iterator i = absl::c_upper_bound(v, 1, std::greater()); EXPECT_EQ(3, i - v.begin()); EXPECT_TRUE(i == v.end()); } TEST_F(NonMutatingTest, EqualRange) { std::pair::iterator, std::list::iterator> p = absl::c_equal_range(sequence_, 2); EXPECT_EQ(1, std::distance(sequence_.begin(), p.first)); EXPECT_EQ(2, std::distance(sequence_.begin(), p.second)); } TEST_F(NonMutatingTest, EqualRangeArray) { auto p = absl::c_equal_range(array_, 2); EXPECT_EQ(1, std::distance(std::begin(array_), p.first)); EXPECT_EQ(2, std::distance(std::begin(array_), p.second)); } TEST_F(NonMutatingTest, EqualRangeWithPredicate) { std::vector v(vector_); std::sort(v.begin(), v.end(), std::greater()); std::pair::iterator, std::vector::iterator> p = absl::c_equal_range(v, 2, std::greater()); EXPECT_EQ(1, std::distance(v.begin(), p.first)); EXPECT_EQ(2, std::distance(v.begin(), p.second)); } TEST_F(NonMutatingTest, BinarySearch) { EXPECT_TRUE(absl::c_binary_search(vector_, 2)); EXPECT_TRUE(absl::c_binary_search(std::vector(vector_), 2)); } TEST_F(NonMutatingTest, BinarySearchWithPredicate) { std::vector v(vector_); std::sort(v.begin(), v.end(), std::greater()); EXPECT_TRUE(absl::c_binary_search(v, 2, std::greater())); EXPECT_TRUE( absl::c_binary_search(std::vector(v), 2, std::greater())); } TEST_F(NonMutatingTest, MinElement) { std::list::iterator i = absl::c_min_element(sequence_); ASSERT_TRUE(i != sequence_.end()); EXPECT_EQ(*i, 1); } TEST_F(NonMutatingTest, MinElementWithPredicate) { std::list::iterator i = absl::c_min_element(sequence_, std::greater()); ASSERT_TRUE(i != sequence_.end()); EXPECT_EQ(*i, 3); } TEST_F(NonMutatingTest, MaxElement) { std::list::iterator i = absl::c_max_element(sequence_); ASSERT_TRUE(i != sequence_.end()); EXPECT_EQ(*i, 3); } TEST_F(NonMutatingTest, MaxElementWithPredicate) { std::list::iterator i = absl::c_max_element(sequence_, std::greater()); ASSERT_TRUE(i != sequence_.end()); EXPECT_EQ(*i, 1); } TEST_F(NonMutatingTest, LexicographicalCompare) { EXPECT_FALSE(absl::c_lexicographical_compare(sequence_, sequence_)); std::vector v; v.push_back(1); v.push_back(2); v.push_back(4); EXPECT_TRUE(absl::c_lexicographical_compare(sequence_, v)); EXPECT_TRUE(absl::c_lexicographical_compare(std::list(sequence_), v)); } TEST_F(NonMutatingTest, LexicographicalCopmareWithPredicate) { EXPECT_FALSE(absl::c_lexicographical_compare(sequence_, sequence_, std::greater())); std::vector v; v.push_back(1); v.push_back(2); v.push_back(4); EXPECT_TRUE( absl::c_lexicographical_compare(v, sequence_, std::greater())); EXPECT_TRUE(absl::c_lexicographical_compare( std::vector(v), std::list(sequence_), std::greater())); } TEST_F(NonMutatingTest, Includes) { std::set s(vector_.begin(), vector_.end()); s.insert(4); EXPECT_TRUE(absl::c_includes(s, vector_)); } TEST_F(NonMutatingTest, IncludesWithPredicate) { std::vector v = {3, 2, 1}; std::set> s(v.begin(), v.end()); s.insert(4); EXPECT_TRUE(absl::c_includes(s, v, std::greater())); } class NumericMutatingTest : public testing::Test { protected: std::list list_ = {1, 2, 3}; std::vector output_; }; TEST_F(NumericMutatingTest, Iota) { absl::c_iota(list_, 5); std::list expected{5, 6, 7}; EXPECT_EQ(list_, expected); } TEST_F(NonMutatingTest, Accumulate) { EXPECT_EQ(absl::c_accumulate(sequence_, 4), 1 + 2 + 3 + 4); } TEST_F(NonMutatingTest, AccumulateWithBinaryOp) { EXPECT_EQ(absl::c_accumulate(sequence_, 4, std::multiplies()), 1 * 2 * 3 * 4); } TEST_F(NonMutatingTest, AccumulateLvalueInit) { int lvalue = 4; EXPECT_EQ(absl::c_accumulate(sequence_, lvalue), 1 + 2 + 3 + 4); } TEST_F(NonMutatingTest, AccumulateWithBinaryOpLvalueInit) { int lvalue = 4; EXPECT_EQ(absl::c_accumulate(sequence_, lvalue, std::multiplies()), 1 * 2 * 3 * 4); } TEST_F(NonMutatingTest, InnerProduct) { EXPECT_EQ(absl::c_inner_product(sequence_, vector_, 1000), 1000 + 1 * 1 + 2 * 2 + 3 * 3); } TEST_F(NonMutatingTest, InnerProductWithBinaryOps) { EXPECT_EQ(absl::c_inner_product(sequence_, vector_, 10, std::multiplies(), std::plus()), 10 * (1 + 1) * (2 + 2) * (3 + 3)); } TEST_F(NonMutatingTest, InnerProductLvalueInit) { int lvalue = 1000; EXPECT_EQ(absl::c_inner_product(sequence_, vector_, lvalue), 1000 + 1 * 1 + 2 * 2 + 3 * 3); } TEST_F(NonMutatingTest, InnerProductWithBinaryOpsLvalueInit) { int lvalue = 10; EXPECT_EQ(absl::c_inner_product(sequence_, vector_, lvalue, std::multiplies(), std::plus()), 10 * (1 + 1) * (2 + 2) * (3 + 3)); } TEST_F(NumericMutatingTest, AdjacentDifference) { auto last = absl::c_adjacent_difference(list_, std::back_inserter(output_)); *last = 1000; std::vector expected{1, 2 - 1, 3 - 2, 1000}; EXPECT_EQ(output_, expected); } TEST_F(NumericMutatingTest, AdjacentDifferenceWithBinaryOp) { auto last = absl::c_adjacent_difference(list_, std::back_inserter(output_), std::multiplies()); *last = 1000; std::vector expected{1, 2 * 1, 3 * 2, 1000}; EXPECT_EQ(output_, expected); } TEST_F(NumericMutatingTest, PartialSum) { auto last = absl::c_partial_sum(list_, std::back_inserter(output_)); *last = 1000; std::vector expected{1, 1 + 2, 1 + 2 + 3, 1000}; EXPECT_EQ(output_, expected); } TEST_F(NumericMutatingTest, PartialSumWithBinaryOp) { auto last = absl::c_partial_sum(list_, std::back_inserter(output_), std::multiplies()); *last = 1000; std::vector expected{1, 1 * 2, 1 * 2 * 3, 1000}; EXPECT_EQ(output_, expected); } TEST_F(NonMutatingTest, LinearSearch) { EXPECT_TRUE(absl::c_linear_search(container_, 3)); EXPECT_FALSE(absl::c_linear_search(container_, 4)); } TEST_F(NonMutatingTest, AllOf) { const std::vector& v = vector_; EXPECT_FALSE(absl::c_all_of(v, [](int x) { return x > 1; })); EXPECT_TRUE(absl::c_all_of(v, [](int x) { return x > 0; })); } TEST_F(NonMutatingTest, AnyOf) { const std::vector& v = vector_; EXPECT_TRUE(absl::c_any_of(v, [](int x) { return x > 2; })); EXPECT_FALSE(absl::c_any_of(v, [](int x) { return x > 5; })); } TEST_F(NonMutatingTest, NoneOf) { const std::vector& v = vector_; EXPECT_FALSE(absl::c_none_of(v, [](int x) { return x > 2; })); EXPECT_TRUE(absl::c_none_of(v, [](int x) { return x > 5; })); } TEST_F(NonMutatingTest, MinMaxElementLess) { std::pair::const_iterator, std::vector::const_iterator> p = absl::c_minmax_element(vector_, std::less()); EXPECT_TRUE(p.first == vector_.begin()); EXPECT_TRUE(p.second == vector_.begin() + 2); } TEST_F(NonMutatingTest, MinMaxElementGreater) { std::pair::const_iterator, std::vector::const_iterator> p = absl::c_minmax_element(vector_, std::greater()); EXPECT_TRUE(p.first == vector_.begin() + 2); EXPECT_TRUE(p.second == vector_.begin()); } TEST_F(NonMutatingTest, MinMaxElementNoPredicate) { std::pair::const_iterator, std::vector::const_iterator> p = absl::c_minmax_element(vector_); EXPECT_TRUE(p.first == vector_.begin()); EXPECT_TRUE(p.second == vector_.begin() + 2); } class SortingTest : public testing::Test { protected: std::list sorted_ = {1, 2, 3, 4}; std::list unsorted_ = {2, 4, 1, 3}; std::list reversed_ = {4, 3, 2, 1}; }; TEST_F(SortingTest, IsSorted) { EXPECT_TRUE(absl::c_is_sorted(sorted_)); EXPECT_FALSE(absl::c_is_sorted(unsorted_)); EXPECT_FALSE(absl::c_is_sorted(reversed_)); } TEST_F(SortingTest, IsSortedWithPredicate) { EXPECT_FALSE(absl::c_is_sorted(sorted_, std::greater())); EXPECT_FALSE(absl::c_is_sorted(unsorted_, std::greater())); EXPECT_TRUE(absl::c_is_sorted(reversed_, std::greater())); } TEST_F(SortingTest, IsSortedUntil) { EXPECT_EQ(1, *absl::c_is_sorted_until(unsorted_)); EXPECT_EQ(4, *absl::c_is_sorted_until(unsorted_, std::greater())); } TEST_F(SortingTest, NthElement) { std::vector unsorted = {2, 4, 1, 3}; absl::c_nth_element(unsorted, unsorted.begin() + 2); EXPECT_THAT(unsorted, ElementsAre(Lt(3), Lt(3), 3, Gt(3))); absl::c_nth_element(unsorted, unsorted.begin() + 2, std::greater()); EXPECT_THAT(unsorted, ElementsAre(Gt(2), Gt(2), 2, Lt(2))); } TEST(MutatingTest, IsPartitioned) { EXPECT_TRUE( absl::c_is_partitioned(std::vector{1, 3, 5, 2, 4, 6}, IsOdd)); EXPECT_FALSE( absl::c_is_partitioned(std::vector{1, 2, 3, 4, 5, 6}, IsOdd)); EXPECT_FALSE( absl::c_is_partitioned(std::vector{2, 4, 6, 1, 3, 5}, IsOdd)); } TEST(MutatingTest, Partition) { std::vector actual = {1, 2, 3, 4, 5}; absl::c_partition(actual, IsOdd); EXPECT_THAT(actual, Truly([](const std::vector& c) { return absl::c_is_partitioned(c, IsOdd); })); } TEST(MutatingTest, StablePartition) { std::vector actual = {1, 2, 3, 4, 5}; absl::c_stable_partition(actual, IsOdd); EXPECT_THAT(actual, ElementsAre(1, 3, 5, 2, 4)); } TEST(MutatingTest, PartitionCopy) { const std::vector initial = {1, 2, 3, 4, 5}; std::vector odds, evens; auto ends = absl::c_partition_copy(initial, back_inserter(odds), back_inserter(evens), IsOdd); *ends.first = 7; *ends.second = 6; EXPECT_THAT(odds, ElementsAre(1, 3, 5, 7)); EXPECT_THAT(evens, ElementsAre(2, 4, 6)); } TEST(MutatingTest, PartitionPoint) { const std::vector initial = {1, 3, 5, 2, 4}; auto middle = absl::c_partition_point(initial, IsOdd); EXPECT_EQ(2, *middle); } TEST(MutatingTest, CopyMiddle) { const std::vector initial = {4, -1, -2, -3, 5}; const std::list input = {1, 2, 3}; const std::vector expected = {4, 1, 2, 3, 5}; std::list test_list(initial.begin(), initial.end()); absl::c_copy(input, ++test_list.begin()); EXPECT_EQ(std::list(expected.begin(), expected.end()), test_list); std::vector test_vector = initial; absl::c_copy(input, test_vector.begin() + 1); EXPECT_EQ(expected, test_vector); } TEST(MutatingTest, CopyFrontInserter) { const std::list initial = {4, 5}; const std::list input = {1, 2, 3}; const std::list expected = {3, 2, 1, 4, 5}; std::list test_list = initial; absl::c_copy(input, std::front_inserter(test_list)); EXPECT_EQ(expected, test_list); } TEST(MutatingTest, CopyBackInserter) { const std::vector initial = {4, 5}; const std::list input = {1, 2, 3}; const std::vector expected = {4, 5, 1, 2, 3}; std::list test_list(initial.begin(), initial.end()); absl::c_copy(input, std::back_inserter(test_list)); EXPECT_EQ(std::list(expected.begin(), expected.end()), test_list); std::vector test_vector = initial; absl::c_copy(input, std::back_inserter(test_vector)); EXPECT_EQ(expected, test_vector); } TEST(MutatingTest, CopyN) { const std::vector initial = {1, 2, 3, 4, 5}; const std::vector expected = {1, 2}; std::vector actual; absl::c_copy_n(initial, 2, back_inserter(actual)); EXPECT_EQ(expected, actual); } TEST(MutatingTest, CopyIf) { const std::list input = {1, 2, 3}; std::vector output; absl::c_copy_if(input, std::back_inserter(output), [](int i) { return i != 2; }); EXPECT_THAT(output, ElementsAre(1, 3)); } TEST(MutatingTest, CopyBackward) { std::vector actual = {1, 2, 3, 4, 5}; std::vector expected = {1, 2, 1, 2, 3}; absl::c_copy_backward(absl::MakeSpan(actual.data(), 3), actual.end()); EXPECT_EQ(expected, actual); } TEST(MutatingTest, Move) { std::vector> src; src.emplace_back(absl::make_unique(1)); src.emplace_back(absl::make_unique(2)); src.emplace_back(absl::make_unique(3)); src.emplace_back(absl::make_unique(4)); src.emplace_back(absl::make_unique(5)); std::vector> dest = {}; absl::c_move(src, std::back_inserter(dest)); EXPECT_THAT(src, Each(IsNull())); EXPECT_THAT(dest, ElementsAre(Pointee(1), Pointee(2), Pointee(3), Pointee(4), Pointee(5))); } TEST(MutatingTest, MoveBackward) { std::vector> actual; actual.emplace_back(absl::make_unique(1)); actual.emplace_back(absl::make_unique(2)); actual.emplace_back(absl::make_unique(3)); actual.emplace_back(absl::make_unique(4)); actual.emplace_back(absl::make_unique(5)); auto subrange = absl::MakeSpan(actual.data(), 3); absl::c_move_backward(subrange, actual.end()); EXPECT_THAT(actual, ElementsAre(IsNull(), IsNull(), Pointee(1), Pointee(2), Pointee(3))); } TEST(MutatingTest, MoveWithRvalue) { auto MakeRValueSrc = [] { std::vector> src; src.emplace_back(absl::make_unique(1)); src.emplace_back(absl::make_unique(2)); src.emplace_back(absl::make_unique(3)); return src; }; std::vector> dest = MakeRValueSrc(); absl::c_move(MakeRValueSrc(), std::back_inserter(dest)); EXPECT_THAT(dest, ElementsAre(Pointee(1), Pointee(2), Pointee(3), Pointee(1), Pointee(2), Pointee(3))); } TEST(MutatingTest, SwapRanges) { std::vector odds = {2, 4, 6}; std::vector evens = {1, 3, 5}; absl::c_swap_ranges(odds, evens); EXPECT_THAT(odds, ElementsAre(1, 3, 5)); EXPECT_THAT(evens, ElementsAre(2, 4, 6)); odds.pop_back(); absl::c_swap_ranges(odds, evens); EXPECT_THAT(odds, ElementsAre(2, 4)); EXPECT_THAT(evens, ElementsAre(1, 3, 6)); absl::c_swap_ranges(evens, odds); EXPECT_THAT(odds, ElementsAre(1, 3)); EXPECT_THAT(evens, ElementsAre(2, 4, 6)); } TEST_F(NonMutatingTest, Transform) { std::vector x{0, 2, 4}, y, z; auto end = absl::c_transform(x, back_inserter(y), std::negate()); EXPECT_EQ(std::vector({0, -2, -4}), y); *end = 7; EXPECT_EQ(std::vector({0, -2, -4, 7}), y); y = {1, 3, 0}; end = absl::c_transform(x, y, back_inserter(z), std::plus()); EXPECT_EQ(std::vector({1, 5, 4}), z); *end = 7; EXPECT_EQ(std::vector({1, 5, 4, 7}), z); z.clear(); y.pop_back(); end = absl::c_transform(x, y, std::back_inserter(z), std::plus()); EXPECT_EQ(std::vector({1, 5}), z); *end = 7; EXPECT_EQ(std::vector({1, 5, 7}), z); z.clear(); std::swap(x, y); end = absl::c_transform(x, y, std::back_inserter(z), std::plus()); EXPECT_EQ(std::vector({1, 5}), z); *end = 7; EXPECT_EQ(std::vector({1, 5, 7}), z); } TEST(MutatingTest, Replace) { const std::vector initial = {1, 2, 3, 1, 4, 5}; const std::vector expected = {4, 2, 3, 4, 4, 5}; std::vector test_vector = initial; absl::c_replace(test_vector, 1, 4); EXPECT_EQ(expected, test_vector); std::list test_list(initial.begin(), initial.end()); absl::c_replace(test_list, 1, 4); EXPECT_EQ(std::list(expected.begin(), expected.end()), test_list); } TEST(MutatingTest, ReplaceIf) { std::vector actual = {1, 2, 3, 4, 5}; const std::vector expected = {0, 2, 0, 4, 0}; absl::c_replace_if(actual, IsOdd, 0); EXPECT_EQ(expected, actual); } TEST(MutatingTest, ReplaceCopy) { const std::vector initial = {1, 2, 3, 1, 4, 5}; const std::vector expected = {4, 2, 3, 4, 4, 5}; std::vector actual; absl::c_replace_copy(initial, back_inserter(actual), 1, 4); EXPECT_EQ(expected, actual); } TEST(MutatingTest, Sort) { std::vector test_vector = {2, 3, 1, 4}; absl::c_sort(test_vector); EXPECT_THAT(test_vector, ElementsAre(1, 2, 3, 4)); } TEST(MutatingTest, SortWithPredicate) { std::vector test_vector = {2, 3, 1, 4}; absl::c_sort(test_vector, std::greater()); EXPECT_THAT(test_vector, ElementsAre(4, 3, 2, 1)); } // For absl::c_stable_sort tests. Needs an operator< that does not cover all // fields so that the test can check the sort preserves order of equal elements. struct Element { int key; int value; friend bool operator<(const Element& e1, const Element& e2) { return e1.key < e2.key; } // Make gmock print useful diagnostics. friend std::ostream& operator<<(std::ostream& o, const Element& e) { return o << "{" << e.key << ", " << e.value << "}"; } }; MATCHER_P2(IsElement, key, value, "") { return arg.key == key && arg.value == value; } TEST(MutatingTest, StableSort) { std::vector test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}}; absl::c_stable_sort(test_vector); EXPECT_THAT(test_vector, ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1), IsElement(2, 0), IsElement(2, 2))); } TEST(MutatingTest, StableSortWithPredicate) { std::vector test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}}; absl::c_stable_sort(test_vector, [](const Element& e1, const Element& e2) { return e2 < e1; }); EXPECT_THAT(test_vector, ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2), IsElement(1, 1), IsElement(1, 0))); } TEST(MutatingTest, ReplaceCopyIf) { const std::vector initial = {1, 2, 3, 4, 5}; const std::vector expected = {0, 2, 0, 4, 0}; std::vector actual; absl::c_replace_copy_if(initial, back_inserter(actual), IsOdd, 0); EXPECT_EQ(expected, actual); } TEST(MutatingTest, Fill) { std::vector actual(5); absl::c_fill(actual, 1); EXPECT_THAT(actual, ElementsAre(1, 1, 1, 1, 1)); } TEST(MutatingTest, FillN) { std::vector actual(5, 0); absl::c_fill_n(actual, 2, 1); EXPECT_THAT(actual, ElementsAre(1, 1, 0, 0, 0)); } TEST(MutatingTest, Generate) { std::vector actual(5); int x = 0; absl::c_generate(actual, [&x]() { return ++x; }); EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5)); } TEST(MutatingTest, GenerateN) { std::vector actual(5, 0); int x = 0; absl::c_generate_n(actual, 3, [&x]() { return ++x; }); EXPECT_THAT(actual, ElementsAre(1, 2, 3, 0, 0)); } TEST(MutatingTest, RemoveCopy) { std::vector actual; absl::c_remove_copy(std::vector{1, 2, 3}, back_inserter(actual), 2); EXPECT_THAT(actual, ElementsAre(1, 3)); } TEST(MutatingTest, RemoveCopyIf) { std::vector actual; absl::c_remove_copy_if(std::vector{1, 2, 3}, back_inserter(actual), IsOdd); EXPECT_THAT(actual, ElementsAre(2)); } TEST(MutatingTest, UniqueCopy) { std::vector actual; absl::c_unique_copy(std::vector{1, 2, 2, 2, 3, 3, 2}, back_inserter(actual)); EXPECT_THAT(actual, ElementsAre(1, 2, 3, 2)); } TEST(MutatingTest, UniqueCopyWithPredicate) { std::vector actual; absl::c_unique_copy(std::vector{1, 2, 3, -1, -2, -3, 1}, back_inserter(actual), [](int x, int y) { return (x < 0) == (y < 0); }); EXPECT_THAT(actual, ElementsAre(1, -1, 1)); } TEST(MutatingTest, Reverse) { std::vector test_vector = {1, 2, 3, 4}; absl::c_reverse(test_vector); EXPECT_THAT(test_vector, ElementsAre(4, 3, 2, 1)); std::list test_list = {1, 2, 3, 4}; absl::c_reverse(test_list); EXPECT_THAT(test_list, ElementsAre(4, 3, 2, 1)); } TEST(MutatingTest, ReverseCopy) { std::vector actual; absl::c_reverse_copy(std::vector{1, 2, 3, 4}, back_inserter(actual)); EXPECT_THAT(actual, ElementsAre(4, 3, 2, 1)); } TEST(MutatingTest, Rotate) { std::vector actual = {1, 2, 3, 4}; auto it = absl::c_rotate(actual, actual.begin() + 2); EXPECT_THAT(actual, testing::ElementsAreArray({3, 4, 1, 2})); EXPECT_EQ(*it, 1); } TEST(MutatingTest, RotateCopy) { std::vector initial = {1, 2, 3, 4}; std::vector actual; auto end = absl::c_rotate_copy(initial, initial.begin() + 2, back_inserter(actual)); *end = 5; EXPECT_THAT(actual, ElementsAre(3, 4, 1, 2, 5)); } template T RandomlySeededPrng() { std::random_device rdev; std::seed_seq::result_type data[T::state_size]; std::generate_n(data, T::state_size, std::ref(rdev)); std::seed_seq prng_seed(data, data + T::state_size); return T(prng_seed); } TEST(MutatingTest, Shuffle) { std::vector actual = {1, 2, 3, 4, 5}; absl::c_shuffle(actual, RandomlySeededPrng()); EXPECT_THAT(actual, UnorderedElementsAre(1, 2, 3, 4, 5)); } TEST(MutatingTest, Sample) { std::vector actual; absl::c_sample(std::vector{1, 2, 3, 4, 5}, std::back_inserter(actual), 3, RandomlySeededPrng()); EXPECT_THAT(actual, IsSubsetOf({1, 2, 3, 4, 5})); EXPECT_THAT(actual, SizeIs(3)); } TEST(MutatingTest, PartialSort) { std::vector sequence{5, 3, 42, 0}; absl::c_partial_sort(sequence, sequence.begin() + 2); EXPECT_THAT(absl::MakeSpan(sequence.data(), 2), ElementsAre(0, 3)); absl::c_partial_sort(sequence, sequence.begin() + 2, std::greater()); EXPECT_THAT(absl::MakeSpan(sequence.data(), 2), ElementsAre(42, 5)); } TEST(MutatingTest, PartialSortCopy) { const std::vector initial = {5, 3, 42, 0}; std::vector actual(2); absl::c_partial_sort_copy(initial, actual); EXPECT_THAT(actual, ElementsAre(0, 3)); absl::c_partial_sort_copy(initial, actual, std::greater()); EXPECT_THAT(actual, ElementsAre(42, 5)); } TEST(MutatingTest, Merge) { std::vector actual; absl::c_merge(std::vector{1, 3, 5}, std::vector{2, 4}, back_inserter(actual)); EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5)); } TEST(MutatingTest, MergeWithComparator) { std::vector actual; absl::c_merge(std::vector{5, 3, 1}, std::vector{4, 2}, back_inserter(actual), std::greater()); EXPECT_THAT(actual, ElementsAre(5, 4, 3, 2, 1)); } TEST(MutatingTest, InplaceMerge) { std::vector actual = {1, 3, 5, 2, 4}; absl::c_inplace_merge(actual, actual.begin() + 3); EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5)); } TEST(MutatingTest, InplaceMergeWithComparator) { std::vector actual = {5, 3, 1, 4, 2}; absl::c_inplace_merge(actual, actual.begin() + 3, std::greater()); EXPECT_THAT(actual, ElementsAre(5, 4, 3, 2, 1)); } class SetOperationsTest : public testing::Test { protected: std::vector a_ = {1, 2, 3}; std::vector b_ = {1, 3, 5}; std::vector a_reversed_ = {3, 2, 1}; std::vector b_reversed_ = {5, 3, 1}; }; TEST_F(SetOperationsTest, SetUnion) { std::vector actual; absl::c_set_union(a_, b_, back_inserter(actual)); EXPECT_THAT(actual, ElementsAre(1, 2, 3, 5)); } TEST_F(SetOperationsTest, SetUnionWithComparator) { std::vector actual; absl::c_set_union(a_reversed_, b_reversed_, back_inserter(actual), std::greater()); EXPECT_THAT(actual, ElementsAre(5, 3, 2, 1)); } TEST_F(SetOperationsTest, SetIntersection) { std::vector actual; absl::c_set_intersection(a_, b_, back_inserter(actual)); EXPECT_THAT(actual, ElementsAre(1, 3)); } TEST_F(SetOperationsTest, SetIntersectionWithComparator) { std::vector actual; absl::c_set_intersection(a_reversed_, b_reversed_, back_inserter(actual), std::greater()); EXPECT_THAT(actual, ElementsAre(3, 1)); } TEST_F(SetOperationsTest, SetDifference) { std::vector actual; absl::c_set_difference(a_, b_, back_inserter(actual)); EXPECT_THAT(actual, ElementsAre(2)); } TEST_F(SetOperationsTest, SetDifferenceWithComparator) { std::vector actual; absl::c_set_difference(a_reversed_, b_reversed_, back_inserter(actual), std::greater()); EXPECT_THAT(actual, ElementsAre(2)); } TEST_F(SetOperationsTest, SetSymmetricDifference) { std::vector actual; absl::c_set_symmetric_difference(a_, b_, back_inserter(actual)); EXPECT_THAT(actual, ElementsAre(2, 5)); } TEST_F(SetOperationsTest, SetSymmetricDifferenceWithComparator) { std::vector actual; absl::c_set_symmetric_difference(a_reversed_, b_reversed_, back_inserter(actual), std::greater()); EXPECT_THAT(actual, ElementsAre(5, 2)); } TEST(HeapOperationsTest, WithoutComparator) { std::vector heap = {1, 2, 3}; EXPECT_FALSE(absl::c_is_heap(heap)); absl::c_make_heap(heap); EXPECT_TRUE(absl::c_is_heap(heap)); heap.push_back(4); EXPECT_EQ(3, absl::c_is_heap_until(heap) - heap.begin()); absl::c_push_heap(heap); EXPECT_EQ(4, heap[0]); absl::c_pop_heap(heap); EXPECT_EQ(4, heap[3]); absl::c_make_heap(heap); absl::c_sort_heap(heap); EXPECT_THAT(heap, ElementsAre(1, 2, 3, 4)); EXPECT_FALSE(absl::c_is_heap(heap)); } TEST(HeapOperationsTest, WithComparator) { using greater = std::greater; std::vector heap = {3, 2, 1}; EXPECT_FALSE(absl::c_is_heap(heap, greater())); absl::c_make_heap(heap, greater()); EXPECT_TRUE(absl::c_is_heap(heap, greater())); heap.push_back(0); EXPECT_EQ(3, absl::c_is_heap_until(heap, greater()) - heap.begin()); absl::c_push_heap(heap, greater()); EXPECT_EQ(0, heap[0]); absl::c_pop_heap(heap, greater()); EXPECT_EQ(0, heap[3]); absl::c_make_heap(heap, greater()); absl::c_sort_heap(heap, greater()); EXPECT_THAT(heap, ElementsAre(3, 2, 1, 0)); EXPECT_FALSE(absl::c_is_heap(heap, greater())); } TEST(MutatingTest, PermutationOperations) { std::vector initial = {1, 2, 3, 4}; std::vector permuted = initial; absl::c_next_permutation(permuted); EXPECT_TRUE(absl::c_is_permutation(initial, permuted)); EXPECT_TRUE(absl::c_is_permutation(initial, permuted, std::equal_to())); std::vector permuted2 = initial; absl::c_prev_permutation(permuted2, std::greater()); EXPECT_EQ(permuted, permuted2); absl::c_prev_permutation(permuted); EXPECT_EQ(initial, permuted); } #if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L TEST(ConstexprTest, Distance) { // Works at compile time with constexpr containers. static_assert(absl::c_distance(std::array()) == 3); } TEST(ConstexprTest, MinElement) { constexpr std::array kArray = {1, 2, 3}; static_assert(*absl::c_min_element(kArray) == 1); } TEST(ConstexprTest, MinElementWithPredicate) { constexpr std::array kArray = {1, 2, 3}; static_assert(*absl::c_min_element(kArray, std::greater()) == 3); } TEST(ConstexprTest, MaxElement) { constexpr std::array kArray = {1, 2, 3}; static_assert(*absl::c_max_element(kArray) == 3); } TEST(ConstexprTest, MaxElementWithPredicate) { constexpr std::array kArray = {1, 2, 3}; static_assert(*absl::c_max_element(kArray, std::greater()) == 1); } TEST(ConstexprTest, MinMaxElement) { static constexpr std::array kArray = {1, 2, 3}; constexpr auto kMinMaxPair = absl::c_minmax_element(kArray); static_assert(*kMinMaxPair.first == 1); static_assert(*kMinMaxPair.second == 3); } TEST(ConstexprTest, MinMaxElementWithPredicate) { static constexpr std::array kArray = {1, 2, 3}; constexpr auto kMinMaxPair = absl::c_minmax_element(kArray, std::greater()); static_assert(*kMinMaxPair.first == 3); static_assert(*kMinMaxPair.second == 1); } #endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L } // namespace abseil-20240722.0/absl/base/000077500000000000000000000000001465274712700152255ustar00rootroot00000000000000abseil-20240722.0/absl/base/BUILD.bazel000066400000000000000000000512621465274712700171110ustar00rootroot00000000000000# # Copyright 2017 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. # load( "//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", "ABSL_DEFAULT_LINKOPTS", "ABSL_TEST_COPTS", ) package( default_visibility = ["//visibility:public"], features = [ "header_modules", "layering_check", "parse_headers", ], ) licenses(["notice"]) cc_library( name = "atomic_hook", hdrs = ["internal/atomic_hook.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [ ":config", ":core_headers", ], ) cc_library( name = "errno_saver", hdrs = ["internal/errno_saver.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [":config"], ) cc_library( name = "log_severity", srcs = ["log_severity.cc"], hdrs = ["log_severity.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ":core_headers", ], ) cc_library( name = "no_destructor", hdrs = ["no_destructor.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ":nullability", ], ) cc_library( name = "nullability", srcs = ["internal/nullability_impl.h"], hdrs = ["nullability.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ":core_headers", "//absl/meta:type_traits", ], ) cc_library( name = "raw_logging_internal", srcs = ["internal/raw_logging.cc"], hdrs = ["internal/raw_logging.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [ ":atomic_hook", ":config", ":core_headers", ":errno_saver", ":log_severity", ], ) cc_library( name = "spinlock_wait", srcs = [ "internal/spinlock_akaros.inc", "internal/spinlock_linux.inc", "internal/spinlock_posix.inc", "internal/spinlock_wait.cc", "internal/spinlock_win32.inc", ], hdrs = ["internal/spinlock_wait.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl/base:__pkg__", ], deps = [ ":base_internal", ":core_headers", ":errno_saver", ], ) cc_library( name = "config", hdrs = [ "config.h", "options.h", "policy_checks.h", ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, ) cc_library( name = "cycleclock_internal", hdrs = [ "internal/cycleclock_config.h", "internal/unscaledcycleclock_config.h", ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [ ":base_internal", ":config", ], ) cc_library( name = "dynamic_annotations", srcs = [ "internal/dynamic_annotations.h", ], hdrs = [ "dynamic_annotations.h", ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ":core_headers", ], ) cc_library( name = "core_headers", hdrs = [ "attributes.h", "const_init.h", "macros.h", "optimization.h", "port.h", "thread_annotations.h", ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ], ) cc_library( name = "malloc_internal", srcs = [ "internal/low_level_alloc.cc", ], hdrs = [ "internal/direct_mmap.h", "internal/low_level_alloc.h", ], copts = ABSL_DEFAULT_COPTS + select({ "//conditions:default": [], }), linkopts = select({ "//absl:msvc_compiler": [], "//absl:clang-cl_compiler": [], "//absl:wasm": [], "//conditions:default": ["-pthread"], }) + ABSL_DEFAULT_LINKOPTS, visibility = [ "//visibility:public", ], deps = [ ":base", ":base_internal", ":config", ":core_headers", ":dynamic_annotations", ":raw_logging_internal", ], ) cc_library( name = "base_internal", hdrs = [ "internal/hide_ptr.h", "internal/identity.h", "internal/inline_variable.h", "internal/invoke.h", "internal/scheduling_mode.h", ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [ ":config", "//absl/meta:type_traits", ], ) cc_library( name = "base", srcs = [ "internal/cycleclock.cc", "internal/spinlock.cc", "internal/sysinfo.cc", "internal/thread_identity.cc", "internal/unscaledcycleclock.cc", ], hdrs = [ "call_once.h", "casts.h", "internal/cycleclock.h", "internal/low_level_scheduling.h", "internal/per_thread_tls.h", "internal/spinlock.h", "internal/sysinfo.h", "internal/thread_identity.h", "internal/tsan_mutex_interface.h", "internal/unscaledcycleclock.h", ], copts = ABSL_DEFAULT_COPTS, linkopts = select({ "//absl:msvc_compiler": [ "-DEFAULTLIB:advapi32.lib", ], "//absl:clang-cl_compiler": [ "-DEFAULTLIB:advapi32.lib", ], "//absl:mingw_compiler": [ "-DEFAULTLIB:advapi32.lib", "-ladvapi32", ], "//absl:wasm": [], "//conditions:default": ["-pthread"], }) + ABSL_DEFAULT_LINKOPTS, deps = [ ":atomic_hook", ":base_internal", ":config", ":core_headers", ":cycleclock_internal", ":dynamic_annotations", ":log_severity", ":nullability", ":raw_logging_internal", ":spinlock_wait", "//absl/meta:type_traits", ], ) cc_library( name = "atomic_hook_test_helper", testonly = True, srcs = ["internal/atomic_hook_test_helper.cc"], hdrs = ["internal/atomic_hook_test_helper.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":atomic_hook", ":core_headers", ], ) cc_test( name = "atomic_hook_test", size = "small", srcs = ["internal/atomic_hook_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":atomic_hook", ":atomic_hook_test_helper", ":core_headers", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "bit_cast_test", size = "small", srcs = [ "bit_cast_test.cc", ], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":base", ":core_headers", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "c_header_test", srcs = ["c_header_test.c"], tags = [ "no_test_wasm", ], deps = [ ":config", ":core_headers", ], ) cc_library( name = "throw_delegate", srcs = ["internal/throw_delegate.cc"], hdrs = ["internal/throw_delegate.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [ ":config", ":raw_logging_internal", ], ) cc_test( name = "throw_delegate_test", srcs = ["throw_delegate_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ":throw_delegate", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "errno_saver_test", size = "small", srcs = ["internal/errno_saver_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":errno_saver", ":strerror", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "exception_testing", testonly = True, hdrs = ["internal/exception_testing.h"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [ ":config", "@com_google_googletest//:gtest", ], ) cc_library( name = "pretty_function", hdrs = ["internal/pretty_function.h"], linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], ) cc_library( name = "exception_safety_testing", testonly = True, srcs = ["internal/exception_safety_testing.cc"], hdrs = ["internal/exception_safety_testing.h"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ":pretty_function", "//absl/memory", "//absl/meta:type_traits", "//absl/strings", "//absl/utility", "@com_google_googletest//:gtest", ], ) cc_test( name = "exception_safety_testing_test", srcs = ["exception_safety_testing_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":exception_safety_testing", "//absl/memory", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "inline_variable_test", size = "small", srcs = [ "inline_variable_test.cc", "inline_variable_test_a.cc", "inline_variable_test_b.cc", "internal/inline_variable_testing.h", ], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":base_internal", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "invoke_test", size = "small", srcs = ["invoke_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":base_internal", "//absl/memory", "//absl/strings", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) # Common test library made available for use in non-absl code that overrides # AbslInternalSpinLockDelay and AbslInternalSpinLockWake. cc_library( name = "spinlock_test_common", testonly = True, srcs = ["spinlock_test_common.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":base", ":base_internal", ":config", ":core_headers", "//absl/synchronization", "@com_google_googletest//:gtest", ], alwayslink = 1, ) cc_test( name = "spinlock_test", size = "medium", srcs = ["spinlock_test_common.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, tags = [ "no_test_wasm", ], deps = [ ":base", ":base_internal", ":config", ":core_headers", "//absl/synchronization", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "spinlock_benchmark_common", testonly = True, srcs = ["internal/spinlock_benchmark.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl/base:__pkg__", ], deps = [ ":base", ":base_internal", ":no_destructor", ":raw_logging_internal", "//absl/synchronization", "@com_github_google_benchmark//:benchmark_main", ], alwayslink = 1, ) cc_binary( name = "spinlock_benchmark", testonly = True, copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, tags = ["benchmark"], visibility = ["//visibility:private"], deps = [ ":spinlock_benchmark_common", ], ) cc_library( name = "endian", hdrs = [ "internal/endian.h", "internal/unaligned_access.h", ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":base", ":config", ":core_headers", ":nullability", ], ) cc_test( name = "endian_test", srcs = ["internal/endian_test.cc"], copts = ABSL_TEST_COPTS, deps = [ ":config", ":endian", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "config_test", srcs = ["config_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", "//absl/synchronization:thread_pool", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "call_once_test", srcs = ["call_once_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":base", ":core_headers", "//absl/synchronization", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "no_destructor_test", srcs = ["no_destructor_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ":no_destructor", ":raw_logging_internal", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_binary( name = "no_destructor_benchmark", testonly = True, srcs = ["no_destructor_benchmark.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, tags = ["benchmark"], visibility = ["//visibility:private"], deps = [ ":no_destructor", ":raw_logging_internal", "@com_github_google_benchmark//:benchmark_main", ], ) cc_test( name = "nullability_test", srcs = ["nullability_test.cc"], deps = [ ":core_headers", ":nullability", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "raw_logging_test", srcs = ["raw_logging_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":raw_logging_internal", "//absl/strings", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "sysinfo_test", size = "small", srcs = ["internal/sysinfo_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":base", "//absl/synchronization", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "low_level_alloc_test", size = "medium", srcs = ["internal/low_level_alloc_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, tags = [ "no_test_ios_x86_64", "no_test_wasm", ], deps = [ ":malloc_internal", "//absl/container:node_hash_map", ], ) cc_test( name = "thread_identity_test", size = "small", srcs = ["internal/thread_identity_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, tags = [ "no_test_wasm", ], deps = [ ":base", ":core_headers", "//absl/synchronization", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "thread_identity_benchmark", srcs = ["internal/thread_identity_benchmark.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, tags = ["benchmark"], visibility = ["//visibility:private"], deps = [ ":base", "//absl/synchronization", "@com_github_google_benchmark//:benchmark_main", "@com_google_googletest//:gtest", ], ) cc_library( name = "scoped_set_env", testonly = True, srcs = ["internal/scoped_set_env.cc"], hdrs = ["internal/scoped_set_env.h"], linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [ ":config", ":raw_logging_internal", ], ) cc_test( name = "scoped_set_env_test", size = "small", srcs = ["internal/scoped_set_env_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":scoped_set_env", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "log_severity_test", size = "small", srcs = ["log_severity_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":log_severity", "//absl/flags:flag_internal", "//absl/flags:marshalling", "//absl/strings", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "strerror", srcs = ["internal/strerror.cc"], hdrs = ["internal/strerror.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [ ":config", ":core_headers", ":errno_saver", ], ) cc_test( name = "strerror_test", size = "small", srcs = ["internal/strerror_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":strerror", "//absl/strings", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_binary( name = "strerror_benchmark", testonly = True, srcs = ["internal/strerror_benchmark.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, tags = ["benchmark"], visibility = ["//visibility:private"], deps = [ ":strerror", "@com_github_google_benchmark//:benchmark_main", ], ) cc_library( name = "fast_type_id", hdrs = ["internal/fast_type_id.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [ ":config", ], ) cc_test( name = "fast_type_id_test", size = "small", srcs = ["internal/fast_type_id_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":fast_type_id", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "prefetch", hdrs = [ "prefetch.h", ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ":core_headers", ], ) cc_test( name = "prefetch_test", size = "small", srcs = [ "prefetch_test.cc", ], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":prefetch", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_library( name = "poison", srcs = [ "internal/poison.cc", ], hdrs = ["internal/poison.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl:__subpackages__", ], deps = [ ":config", ":core_headers", ":malloc_internal", ], ) cc_test( name = "poison_test", size = "small", timeout = "short", srcs = [ "internal/poison_test.cc", ], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", ":poison", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "unique_small_name_test", size = "small", srcs = ["internal/unique_small_name_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, linkstatic = 1, deps = [ ":core_headers", "//absl/strings", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) cc_test( name = "optimization_test", size = "small", srcs = ["optimization_test.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":core_headers", "//absl/types:optional", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) abseil-20240722.0/absl/base/CMakeLists.txt000066400000000000000000000306661465274712700200000ustar00rootroot00000000000000# # Copyright 2017 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. # find_library(LIBRT rt) # Internal-only target, do not depend on directly. absl_cc_library( NAME atomic_hook HDRS "internal/atomic_hook.h" DEPS absl::config absl::core_headers COPTS ${ABSL_DEFAULT_COPTS} ) # Internal-only target, do not depend on directly. absl_cc_library( NAME errno_saver HDRS "internal/errno_saver.h" DEPS absl::config COPTS ${ABSL_DEFAULT_COPTS} ) absl_cc_library( NAME log_severity HDRS "log_severity.h" SRCS "log_severity.cc" DEPS absl::config absl::core_headers COPTS ${ABSL_DEFAULT_COPTS} ) absl_cc_library( NAME no_destructor HDRS "no_destructor.h" DEPS absl::config absl::nullability COPTS ${ABSL_DEFAULT_COPTS} ) absl_cc_library( NAME nullability HDRS "nullability.h" SRCS "internal/nullability_impl.h" DEPS absl::config absl::core_headers absl::type_traits COPTS ${ABSL_DEFAULT_COPTS} ) absl_cc_test( NAME nullability_test SRCS "nullability_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::core_headers absl::nullability GTest::gtest_main ) # Internal-only target, do not depend on directly. absl_cc_library( NAME raw_logging_internal HDRS "internal/raw_logging.h" SRCS "internal/raw_logging.cc" DEPS absl::atomic_hook absl::config absl::core_headers absl::errno_saver absl::log_severity COPTS ${ABSL_DEFAULT_COPTS} ) # Internal-only target, do not depend on directly. absl_cc_library( NAME spinlock_wait HDRS "internal/spinlock_wait.h" SRCS "internal/spinlock_akaros.inc" "internal/spinlock_linux.inc" "internal/spinlock_posix.inc" "internal/spinlock_wait.cc" "internal/spinlock_win32.inc" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::base_internal absl::core_headers absl::errno_saver ) absl_cc_library( NAME config HDRS "config.h" "options.h" "policy_checks.h" COPTS ${ABSL_DEFAULT_COPTS} PUBLIC ) absl_cc_library( NAME dynamic_annotations HDRS "dynamic_annotations.h" SRCS "internal/dynamic_annotations.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::config PUBLIC ) absl_cc_library( NAME core_headers HDRS "attributes.h" "const_init.h" "macros.h" "optimization.h" "port.h" "thread_annotations.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::config PUBLIC ) # Internal-only target, do not depend on directly. absl_cc_library( NAME malloc_internal HDRS "internal/direct_mmap.h" "internal/low_level_alloc.h" SRCS "internal/low_level_alloc.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::base absl::base_internal absl::config absl::core_headers absl::dynamic_annotations absl::raw_logging_internal Threads::Threads ) # Internal-only target, do not depend on directly. absl_cc_library( NAME base_internal HDRS "internal/hide_ptr.h" "internal/identity.h" "internal/inline_variable.h" "internal/invoke.h" "internal/scheduling_mode.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::config absl::type_traits ) absl_cc_library( NAME base HDRS "call_once.h" "casts.h" "internal/cycleclock.h" "internal/cycleclock_config.h" "internal/low_level_scheduling.h" "internal/per_thread_tls.h" "internal/spinlock.h" "internal/sysinfo.h" "internal/thread_identity.h" "internal/tsan_mutex_interface.h" "internal/unscaledcycleclock.h" "internal/unscaledcycleclock_config.h" SRCS "internal/cycleclock.cc" "internal/spinlock.cc" "internal/sysinfo.cc" "internal/thread_identity.cc" "internal/unscaledcycleclock.cc" COPTS ${ABSL_DEFAULT_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} $<$:-lrt> $<$:-ladvapi32> DEPS absl::atomic_hook absl::base_internal absl::config absl::core_headers absl::dynamic_annotations absl::log_severity absl::nullability absl::raw_logging_internal absl::spinlock_wait absl::type_traits Threads::Threads PUBLIC ) # Internal-only target, do not depend on directly. absl_cc_library( NAME throw_delegate HDRS "internal/throw_delegate.h" SRCS "internal/throw_delegate.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::config absl::raw_logging_internal ) # Internal-only target, do not depend on directly. absl_cc_library( NAME exception_testing HDRS "internal/exception_testing.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::config GTest::gtest TESTONLY ) # Internal-only target, do not depend on directly. absl_cc_library( NAME pretty_function HDRS "internal/pretty_function.h" COPTS ${ABSL_DEFAULT_COPTS} ) # Internal-only target, do not depend on directly. absl_cc_library( NAME exception_safety_testing HDRS "internal/exception_safety_testing.h" SRCS "internal/exception_safety_testing.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::config absl::pretty_function absl::memory absl::meta absl::strings absl::utility GTest::gtest TESTONLY ) absl_cc_test( NAME absl_exception_safety_testing_test SRCS "exception_safety_testing_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::exception_safety_testing absl::memory GTest::gtest_main ) # Internal-only target, do not depend on directly. absl_cc_library( NAME atomic_hook_test_helper SRCS "internal/atomic_hook_test_helper.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::atomic_hook absl::core_headers TESTONLY ) absl_cc_test( NAME atomic_hook_test SRCS "internal/atomic_hook_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::atomic_hook_test_helper absl::atomic_hook absl::core_headers GTest::gmock GTest::gtest_main ) absl_cc_test( NAME bit_cast_test SRCS "bit_cast_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base absl::core_headers GTest::gtest_main ) absl_cc_test( NAME errno_saver_test SRCS "internal/errno_saver_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::errno_saver absl::strerror GTest::gmock GTest::gtest_main ) absl_cc_test( NAME throw_delegate_test SRCS "throw_delegate_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base absl::config absl::throw_delegate GTest::gtest_main ) absl_cc_test( NAME inline_variable_test SRCS "internal/inline_variable_testing.h" "inline_variable_test.cc" "inline_variable_test_a.cc" "inline_variable_test_b.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base_internal GTest::gtest_main ) absl_cc_test( NAME invoke_test SRCS "invoke_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base_internal absl::memory absl::strings GTest::gmock GTest::gtest_main ) # Internal-only target, do not depend on directly. absl_cc_library( NAME spinlock_test_common SRCS "spinlock_test_common.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base absl::config absl::base_internal absl::core_headers absl::synchronization GTest::gtest TESTONLY ) # On bazel BUILD this target use "alwayslink = 1" which is not implemented here absl_cc_test( NAME spinlock_test SRCS "spinlock_test_common.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base absl::base_internal absl::config absl::core_headers absl::synchronization GTest::gtest_main ) # Internal-only target, do not depend on directly. absl_cc_library( NAME endian HDRS "internal/endian.h" "internal/unaligned_access.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::base absl::config absl::core_headers absl::nullability PUBLIC ) absl_cc_test( NAME endian_test SRCS "internal/endian_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base absl::config absl::endian GTest::gtest_main ) absl_cc_test( NAME config_test SRCS "config_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::config absl::synchronization GTest::gtest_main ) absl_cc_test( NAME call_once_test SRCS "call_once_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base absl::core_headers absl::synchronization GTest::gtest_main ) absl_cc_test( NAME no_destructor_test SRCS "no_destructor_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::no_destructor absl::config absl::raw_logging_internal GTest::gtest_main ) absl_cc_test( NAME raw_logging_test SRCS "raw_logging_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::raw_logging_internal absl::strings GTest::gtest_main ) absl_cc_test( NAME sysinfo_test SRCS "internal/sysinfo_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base absl::synchronization GTest::gtest_main ) absl_cc_test( NAME low_level_alloc_test SRCS "internal/low_level_alloc_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::malloc_internal absl::node_hash_map Threads::Threads ) absl_cc_test( NAME thread_identity_test SRCS "internal/thread_identity_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base absl::core_headers absl::synchronization Threads::Threads GTest::gtest_main ) # Internal-only target, do not depend on directly. absl_cc_library( NAME scoped_set_env SRCS "internal/scoped_set_env.cc" HDRS "internal/scoped_set_env.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS absl::config absl::raw_logging_internal ) absl_cc_test( NAME scoped_set_env_test SRCS "internal/scoped_set_env_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::scoped_set_env GTest::gtest_main ) absl_cc_test( NAME cmake_thread_test SRCS "internal/cmake_thread_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::base ) absl_cc_test( NAME log_severity_test SRCS "log_severity_test.cc" DEPS absl::flags_internal absl::flags_marshalling absl::log_severity absl::strings GTest::gmock GTest::gtest_main ) # Internal-only target, do not depend on directly. absl_cc_library( NAME strerror SRCS "internal/strerror.cc" HDRS "internal/strerror.h" COPTS ${ABSL_DEFAULT_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS absl::config absl::core_headers absl::errno_saver ) absl_cc_test( NAME strerror_test SRCS "internal/strerror_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::strerror absl::strings GTest::gmock GTest::gtest_main ) # Internal-only target, do not depend on directly. absl_cc_library( NAME fast_type_id HDRS "internal/fast_type_id.h" COPTS ${ABSL_DEFAULT_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS absl::config ) absl_cc_test( NAME fast_type_id_test SRCS "internal/fast_type_id_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::fast_type_id GTest::gtest_main ) absl_cc_library( NAME prefetch HDRS "prefetch.h" COPTS ${ABSL_DEFAULT_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS absl::config absl::core_headers ) absl_cc_test( NAME prefetch_test SRCS "prefetch_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::prefetch GTest::gtest_main ) absl_cc_test( NAME optimization_test SRCS "optimization_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::core_headers absl::optional GTest::gtest_main ) absl_cc_library( NAME poison SRCS "internal/poison.cc" HDRS "internal/poison.h" COPTS ${ABSL_DEFAULT_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS absl::config absl::core_headers absl::malloc_internal ) absl_cc_test( NAME poison_test SRCS "internal/poison_test.cc" COPTS ${ABSL_TEST_COPTS} DEPS absl::config absl::poison GTest::gtest_main ) abseil-20240722.0/absl/base/attributes.h000066400000000000000000001141001465274712700175610ustar00rootroot00000000000000// Copyright 2017 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. // // This header file defines macros for declaring attributes for functions, // types, and variables. // // These macros are used within Abseil and allow the compiler to optimize, where // applicable, certain function calls. // // Most macros here are exposing GCC or Clang features, and are stubbed out for // other compilers. // // GCC attributes documentation: // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html // // Most attributes in this file are already supported by GCC 4.7. However, some // of them are not supported in older version of Clang. Thus, we check // `__has_attribute()` first. If the check fails, we check if we are on GCC and // assume the attribute exists on GCC (which is verified on GCC 4.7). #ifndef ABSL_BASE_ATTRIBUTES_H_ #define ABSL_BASE_ATTRIBUTES_H_ #include "absl/base/config.h" // ABSL_HAVE_ATTRIBUTE // // A function-like feature checking macro that is a wrapper around // `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a // nonzero constant integer if the attribute is supported or 0 if not. // // It evaluates to zero if `__has_attribute` is not defined by the compiler. // // GCC: https://gcc.gnu.org/gcc-5/changes.html // Clang: https://clang.llvm.org/docs/LanguageExtensions.html #ifdef __has_attribute #define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x) #else #define ABSL_HAVE_ATTRIBUTE(x) 0 #endif // ABSL_HAVE_CPP_ATTRIBUTE // // A function-like feature checking macro that accepts C++11 style attributes. // It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 // (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't // find `__has_cpp_attribute`, will evaluate to 0. #if defined(__cplusplus) && defined(__has_cpp_attribute) // NOTE: requiring __cplusplus above should not be necessary, but // works around https://bugs.llvm.org/show_bug.cgi?id=23435. #define ABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) #else #define ABSL_HAVE_CPP_ATTRIBUTE(x) 0 #endif // ----------------------------------------------------------------------------- // Function Attributes // ----------------------------------------------------------------------------- // // GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html // Clang: https://clang.llvm.org/docs/AttributeReference.html // ABSL_PRINTF_ATTRIBUTE // ABSL_SCANF_ATTRIBUTE // // Tells the compiler to perform `printf` format string checking if the // compiler supports it; see the 'format' attribute in // . // // Note: As the GCC manual states, "[s]ince non-static C++ methods // have an implicit 'this' argument, the arguments of such methods // should be counted from two, not one." #if ABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) #define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \ __attribute__((__format__(__printf__, string_index, first_to_check))) #define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \ __attribute__((__format__(__scanf__, string_index, first_to_check))) #else #define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) #define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) #endif // ABSL_ATTRIBUTE_ALWAYS_INLINE // ABSL_ATTRIBUTE_NOINLINE // // Forces functions to either inline or not inline. Introduced in gcc 3.1. #if ABSL_HAVE_ATTRIBUTE(always_inline) || \ (defined(__GNUC__) && !defined(__clang__)) #define ABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) #define ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 #else #define ABSL_ATTRIBUTE_ALWAYS_INLINE #endif #if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) #define ABSL_ATTRIBUTE_NOINLINE __attribute__((noinline)) #define ABSL_HAVE_ATTRIBUTE_NOINLINE 1 #else #define ABSL_ATTRIBUTE_NOINLINE #endif // ABSL_ATTRIBUTE_NO_TAIL_CALL // // Prevents the compiler from optimizing away stack frames for functions which // end in a call to another function. #if ABSL_HAVE_ATTRIBUTE(disable_tail_calls) #define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 #define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls)) #elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__) #define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 #define ABSL_ATTRIBUTE_NO_TAIL_CALL \ __attribute__((optimize("no-optimize-sibling-calls"))) #else #define ABSL_ATTRIBUTE_NO_TAIL_CALL #define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 #endif // ABSL_ATTRIBUTE_WEAK // // Tags a function as weak for the purposes of compilation and linking. // Weak attributes did not work properly in LLVM's Windows backend before // 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 // for further information. // The MinGW compiler doesn't complain about the weak attribute until the link // step, presumably because Windows doesn't use ELF binaries. #if (ABSL_HAVE_ATTRIBUTE(weak) || \ (defined(__GNUC__) && !defined(__clang__))) && \ (!defined(_WIN32) || (defined(__clang__) && __clang_major__ >= 9)) && \ !defined(__MINGW32__) #undef ABSL_ATTRIBUTE_WEAK #define ABSL_ATTRIBUTE_WEAK __attribute__((weak)) #define ABSL_HAVE_ATTRIBUTE_WEAK 1 #else #define ABSL_ATTRIBUTE_WEAK #define ABSL_HAVE_ATTRIBUTE_WEAK 0 #endif // ABSL_ATTRIBUTE_NONNULL // // Tells the compiler either (a) that a particular function parameter // should be a non-null pointer, or (b) that all pointer arguments should // be non-null. // // Note: As the GCC manual states, "[s]ince non-static C++ methods // have an implicit 'this' argument, the arguments of such methods // should be counted from two, not one." // // Args are indexed starting at 1. // // For non-static class member functions, the implicit `this` argument // is arg 1, and the first explicit argument is arg 2. For static class member // functions, there is no implicit `this`, and the first explicit argument is // arg 1. // // Example: // // /* arg_a cannot be null, but arg_b can */ // void Function(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(1); // // class C { // /* arg_a cannot be null, but arg_b can */ // void Method(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(2); // // /* arg_a cannot be null, but arg_b can */ // static void StaticMethod(void* arg_a, void* arg_b) // ABSL_ATTRIBUTE_NONNULL(1); // }; // // If no arguments are provided, then all pointer arguments should be non-null. // // /* No pointer arguments may be null. */ // void Function(void* arg_a, void* arg_b, int arg_c) ABSL_ATTRIBUTE_NONNULL(); // // NOTE: The GCC nonnull attribute actually accepts a list of arguments, but // ABSL_ATTRIBUTE_NONNULL does not. #if ABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) #define ABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) #else #define ABSL_ATTRIBUTE_NONNULL(...) #endif // ABSL_ATTRIBUTE_NORETURN // // Tells the compiler that a given function never returns. // // Deprecated: Prefer the `[[noreturn]]` attribute standardized by C++11 over // this macro. #if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) #define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) #elif defined(_MSC_VER) #define ABSL_ATTRIBUTE_NORETURN __declspec(noreturn) #else #define ABSL_ATTRIBUTE_NORETURN #endif // ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // // Tells the AddressSanitizer (or other memory testing tools) to ignore a given // function. Useful for cases when a function reads random locations on stack, // calls _exit from a cloned subprocess, deliberately accesses buffer // out of bounds or does other scary things with memory. // NOTE: GCC supports AddressSanitizer(asan) since 4.8. // https://gcc.gnu.org/gcc-4.8/changes.html #if defined(ABSL_HAVE_ADDRESS_SANITIZER) && \ ABSL_HAVE_ATTRIBUTE(no_sanitize_address) #define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) #elif defined(ABSL_HAVE_ADDRESS_SANITIZER) && defined(_MSC_VER) && \ _MSC_VER >= 1928 // https://docs.microsoft.com/en-us/cpp/cpp/no-sanitize-address #define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __declspec(no_sanitize_address) #elif defined(ABSL_HAVE_HWADDRESS_SANITIZER) && ABSL_HAVE_ATTRIBUTE(no_sanitize) // HWAddressSanitizer is a sanitizer similar to AddressSanitizer, which uses CPU // features to detect similar bugs with less CPU and memory overhead. // NOTE: GCC supports HWAddressSanitizer(hwasan) since 11. // https://gcc.gnu.org/gcc-11/changes.html #define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS \ __attribute__((no_sanitize("hwaddress"))) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS #endif // ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // // Tells the MemorySanitizer to relax the handling of a given function. All "Use // of uninitialized value" warnings from such functions will be suppressed, and // all values loaded from memory will be considered fully initialized. This // attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute // above, but deals with initialized-ness rather than addressability issues. // NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. #if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory) #define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY #endif // ABSL_ATTRIBUTE_NO_SANITIZE_THREAD // // Tells the ThreadSanitizer to not instrument a given function. // NOTE: GCC supports ThreadSanitizer(tsan) since 4.8. // https://gcc.gnu.org/gcc-4.8/changes.html #if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread) #define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD #endif // ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED // // Tells the UndefinedSanitizer to ignore a given function. Useful for cases // where certain behavior (eg. division by zero) is being used intentionally. // NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9. // https://gcc.gnu.org/gcc-4.9/changes.html #if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined) #define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ __attribute__((no_sanitize_undefined)) #elif ABSL_HAVE_ATTRIBUTE(no_sanitize) #define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ __attribute__((no_sanitize("undefined"))) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED #endif // ABSL_ATTRIBUTE_NO_SANITIZE_CFI // // Tells the ControlFlowIntegrity sanitizer to not instrument a given function. // See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. #if ABSL_HAVE_ATTRIBUTE(no_sanitize) && defined(__llvm__) #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI #endif // ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK // // Tells the SafeStack to not instrument a given function. // See https://clang.llvm.org/docs/SafeStack.html for details. #if ABSL_HAVE_ATTRIBUTE(no_sanitize) #define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ __attribute__((no_sanitize("safe-stack"))) #else #define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK #endif // ABSL_ATTRIBUTE_RETURNS_NONNULL // // Tells the compiler that a particular function never returns a null pointer. #if ABSL_HAVE_ATTRIBUTE(returns_nonnull) #define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) #else #define ABSL_ATTRIBUTE_RETURNS_NONNULL #endif // ABSL_HAVE_ATTRIBUTE_SECTION // // Indicates whether labeled sections are supported. Weak symbol support is // a prerequisite. Labeled sections are not supported on Darwin/iOS. #ifdef ABSL_HAVE_ATTRIBUTE_SECTION #error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set #elif (ABSL_HAVE_ATTRIBUTE(section) || \ (defined(__GNUC__) && !defined(__clang__))) && \ !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK #define ABSL_HAVE_ATTRIBUTE_SECTION 1 // ABSL_ATTRIBUTE_SECTION // // Tells the compiler/linker to put a given function into a section and define // `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. // This functionality is supported by GNU linker. Any function annotated with // `ABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into // whatever section its caller is placed into. // #ifndef ABSL_ATTRIBUTE_SECTION #define ABSL_ATTRIBUTE_SECTION(name) \ __attribute__((section(#name))) __attribute__((noinline)) #endif // ABSL_ATTRIBUTE_SECTION_VARIABLE // // Tells the compiler/linker to put a given variable into a section and define // `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. // This functionality is supported by GNU linker. #ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE #ifdef _AIX // __attribute__((section(#name))) on AIX is achieved by using the `.csect` // psudo op which includes an additional integer as part of its syntax indcating // alignment. If data fall under different alignments then you might get a // compilation error indicating a `Section type conflict`. #define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) #else #define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) #endif #endif // ABSL_DECLARE_ATTRIBUTE_SECTION_VARS // // A weak section declaration to be used as a global declaration // for ABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link // even without functions with ABSL_ATTRIBUTE_SECTION(name). // ABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's // a no-op on ELF but not on Mach-O. // #ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS #define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \ extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK #endif #ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS #define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) #define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) #endif // ABSL_ATTRIBUTE_SECTION_START // // Returns `void*` pointers to start/end of a section of code with // functions having ABSL_ATTRIBUTE_SECTION(name). // Returns 0 if no such functions exist. // One must ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and // link. // #define ABSL_ATTRIBUTE_SECTION_START(name) \ (reinterpret_cast(__start_##name)) #define ABSL_ATTRIBUTE_SECTION_STOP(name) \ (reinterpret_cast(__stop_##name)) #else // !ABSL_HAVE_ATTRIBUTE_SECTION #define ABSL_HAVE_ATTRIBUTE_SECTION 0 // provide dummy definitions #define ABSL_ATTRIBUTE_SECTION(name) #define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) #define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) #define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) #define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) #define ABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast(0)) #define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(0)) #endif // ABSL_ATTRIBUTE_SECTION // ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC // // Support for aligning the stack on 32-bit x86. #if ABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ (defined(__GNUC__) && !defined(__clang__)) #if defined(__i386__) #define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ __attribute__((force_align_arg_pointer)) #define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) #elif defined(__x86_64__) #define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) #define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC #else // !__i386__ && !__x86_64 #define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) #define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC #endif // __i386__ #else #define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC #define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) #endif // ABSL_MUST_USE_RESULT // // Tells the compiler to warn about unused results. // // For code or headers that are assured to only build with C++17 and up, prefer // just using the standard `[[nodiscard]]` directly over this macro. // // When annotating a function, it must appear as the first part of the // declaration or definition. The compiler will warn if the return value from // such a function is unused: // // ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket(); // AllocateSprocket(); // Triggers a warning. // // When annotating a class, it is equivalent to annotating every function which // returns an instance. // // class ABSL_MUST_USE_RESULT Sprocket {}; // Sprocket(); // Triggers a warning. // // Sprocket MakeSprocket(); // MakeSprocket(); // Triggers a warning. // // Note that references and pointers are not instances: // // Sprocket* SprocketPointer(); // SprocketPointer(); // Does *not* trigger a warning. // // ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result // warning. For that, warn_unused_result is used only for clang but not for gcc. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 // // Note: past advice was to place the macro after the argument list. // // TODO(b/176172494): Use ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) when all code is // compliant with the stricter [[nodiscard]]. #if defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result) #define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result)) #else #define ABSL_MUST_USE_RESULT #endif // ABSL_ATTRIBUTE_HOT, ABSL_ATTRIBUTE_COLD // // Tells GCC that a function is hot or cold. GCC can use this information to // improve static analysis, i.e. a conditional branch to a cold function // is likely to be not-taken. // This annotation is used for function declarations. // // Example: // // int foo() ABSL_ATTRIBUTE_HOT; #if ABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) #define ABSL_ATTRIBUTE_HOT __attribute__((hot)) #else #define ABSL_ATTRIBUTE_HOT #endif #if ABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) #define ABSL_ATTRIBUTE_COLD __attribute__((cold)) #else #define ABSL_ATTRIBUTE_COLD #endif // ABSL_XRAY_ALWAYS_INSTRUMENT, ABSL_XRAY_NEVER_INSTRUMENT, ABSL_XRAY_LOG_ARGS // // We define the ABSL_XRAY_ALWAYS_INSTRUMENT and ABSL_XRAY_NEVER_INSTRUMENT // macro used as an attribute to mark functions that must always or never be // instrumented by XRay. Currently, this is only supported in Clang/LLVM. // // For reference on the LLVM XRay instrumentation, see // http://llvm.org/docs/XRay.html. // // A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration // will always get the XRay instrumentation sleds. These sleds may introduce // some binary size and runtime overhead and must be used sparingly. // // These attributes only take effect when the following conditions are met: // // * The file/target is built in at least C++11 mode, with a Clang compiler // that supports XRay attributes. // * The file/target is built with the -fxray-instrument flag set for the // Clang/LLVM compiler. // * The function is defined in the translation unit (the compiler honors the // attribute in either the definition or the declaration, and must match). // // There are cases when, even when building with XRay instrumentation, users // might want to control specifically which functions are instrumented for a // particular build using special-case lists provided to the compiler. These // special case lists are provided to Clang via the // -fxray-always-instrument=... and -fxray-never-instrument=... flags. The // attributes in source take precedence over these special-case lists. // // To disable the XRay attributes at build-time, users may define // ABSL_NO_XRAY_ATTRIBUTES. Do NOT define ABSL_NO_XRAY_ATTRIBUTES on specific // packages/targets, as this may lead to conflicting definitions of functions at // link-time. // // XRay isn't currently supported on Android: // https://github.com/android/ndk/issues/368 #if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \ !defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__) #define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] #define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] #if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args) #define ABSL_XRAY_LOG_ARGS(N) \ [[clang::xray_always_instrument, clang::xray_log_args(N)]] #else #define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]] #endif #else #define ABSL_XRAY_ALWAYS_INSTRUMENT #define ABSL_XRAY_NEVER_INSTRUMENT #define ABSL_XRAY_LOG_ARGS(N) #endif // ABSL_ATTRIBUTE_REINITIALIZES // // Indicates that a member function reinitializes the entire object to a known // state, independent of the previous state of the object. // // The clang-tidy check bugprone-use-after-move allows member functions marked // with this attribute to be called on objects that have been moved from; // without the attribute, this would result in a use-after-move warning. #if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) #define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] #else #define ABSL_ATTRIBUTE_REINITIALIZES #endif // ----------------------------------------------------------------------------- // Variable Attributes // ----------------------------------------------------------------------------- // ABSL_ATTRIBUTE_UNUSED // // Prevents the compiler from complaining about variables that appear unused. // // For code or headers that are assured to only build with C++17 and up, prefer // just using the standard '[[maybe_unused]]' directly over this macro. // // Due to differences in positioning requirements between the old, compiler // specific __attribute__ syntax and the now standard [[maybe_unused]], this // macro does not attempt to take advantage of '[[maybe_unused]]'. #if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) #undef ABSL_ATTRIBUTE_UNUSED #define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) #else #define ABSL_ATTRIBUTE_UNUSED #endif // ABSL_ATTRIBUTE_INITIAL_EXEC // // Tells the compiler to use "initial-exec" mode for a thread-local variable. // See http://people.redhat.com/drepper/tls.pdf for the gory details. #if ABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) #define ABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) #else #define ABSL_ATTRIBUTE_INITIAL_EXEC #endif // ABSL_ATTRIBUTE_PACKED // // Instructs the compiler not to use natural alignment for a tagged data // structure, but instead to reduce its alignment to 1. // // Therefore, DO NOT APPLY THIS ATTRIBUTE TO STRUCTS CONTAINING ATOMICS. Doing // so can cause atomic variables to be mis-aligned and silently violate // atomicity on x86. // // This attribute can either be applied to members of a structure or to a // structure in its entirety. Applying this attribute (judiciously) to a // structure in its entirety to optimize the memory footprint of very // commonly-used structs is fine. Do not apply this attribute to a structure in // its entirety if the purpose is to control the offsets of the members in the // structure. Instead, apply this attribute only to structure members that need // it. // // When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the // natural alignment of structure members not annotated is preserved. Aligned // member accesses are faster than non-aligned member accesses even if the // targeted microprocessor supports non-aligned accesses. #if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) #define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) #else #define ABSL_ATTRIBUTE_PACKED #endif // ABSL_ATTRIBUTE_FUNC_ALIGN // // Tells the compiler to align the function start at least to certain // alignment boundary #if ABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) #define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) #else #define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) #endif // ABSL_FALLTHROUGH_INTENDED // // Annotates implicit fall-through between switch labels, allowing a case to // indicate intentional fallthrough and turn off warnings about any lack of a // `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by // a semicolon and can be used in most places where `break` can, provided that // no statements exist between it and the next switch label. // // Example: // // switch (x) { // case 40: // case 41: // if (truth_is_out_there) { // ++x; // ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations // // in comments // } else { // return x; // } // case 42: // ... // // Notes: When supported, GCC and Clang can issue a warning on switch labels // with unannotated fallthrough using the warning `-Wimplicit-fallthrough`. See // clang documentation on language extensions for details: // https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough // // When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro has // no effect on diagnostics. In any case this macro has no effect on runtime // behavior and performance of code. #ifdef ABSL_FALLTHROUGH_INTENDED #error "ABSL_FALLTHROUGH_INTENDED should not be defined." #elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough) #define ABSL_FALLTHROUGH_INTENDED [[fallthrough]] #elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough) #define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]] #elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough) #define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]] #else #define ABSL_FALLTHROUGH_INTENDED \ do { \ } while (0) #endif // ABSL_DEPRECATED() // // Marks a deprecated class, struct, enum, function, method and variable // declarations. The macro argument is used as a custom diagnostic message (e.g. // suggestion of a better alternative). // // For code or headers that are assured to only build with C++14 and up, prefer // just using the standard `[[deprecated("message")]]` directly over this macro. // // Examples: // // class ABSL_DEPRECATED("Use Bar instead") Foo {...}; // // ABSL_DEPRECATED("Use Baz() instead") void Bar() {...} // // template // ABSL_DEPRECATED("Use DoThat() instead") // void DoThis(); // // enum FooEnum { // kBar ABSL_DEPRECATED("Use kBaz instead"), // }; // // Every usage of a deprecated entity will trigger a warning when compiled with // GCC/Clang's `-Wdeprecated-declarations` option. Google's production toolchain // turns this warning off by default, instead relying on clang-tidy to report // new uses of deprecated code. #if ABSL_HAVE_ATTRIBUTE(deprecated) #define ABSL_DEPRECATED(message) __attribute__((deprecated(message))) #else #define ABSL_DEPRECATED(message) #endif // When deprecating Abseil code, it is sometimes necessary to turn off the // warning within Abseil, until the deprecated code is actually removed. The // deprecated code can be surrounded with these directives to achieve that // result. // // class ABSL_DEPRECATED("Use Bar instead") Foo; // // ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING // Baz ComputeBazFromFoo(Foo f); // ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING #if defined(__GNUC__) || defined(__clang__) // Clang also supports these GCC pragmas. #define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") #define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \ _Pragma("GCC diagnostic pop") #elif defined(_MSC_VER) #define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \ _Pragma("warning(push)") _Pragma("warning(disable: 4996)") #define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \ _Pragma("warning(pop)") #else #define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING #define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING #endif // defined(__GNUC__) || defined(__clang__) // ABSL_CONST_INIT // // A variable declaration annotated with the `ABSL_CONST_INIT` attribute will // not compile (on supported platforms) unless the variable has a constant // initializer. This is useful for variables with static and thread storage // duration, because it guarantees that they will not suffer from the so-called // "static init order fiasco". // // This attribute must be placed on the initializing declaration of the // variable. Some compilers will give a -Wmissing-constinit warning when this // attribute is placed on some other declaration but missing from the // initializing declaration. // // In some cases (notably with thread_local variables), `ABSL_CONST_INIT` can // also be used in a non-initializing declaration to tell the compiler that a // variable is already initialized, reducing overhead that would otherwise be // incurred by a hidden guard variable. Thus annotating all declarations with // this attribute is recommended to potentially enhance optimization. // // Example: // // class MyClass { // public: // ABSL_CONST_INIT static MyType my_var; // }; // // ABSL_CONST_INIT MyType MyClass::my_var = MakeMyType(...); // // For code or headers that are assured to only build with C++20 and up, prefer // just using the standard `constinit` keyword directly over this macro. // // Note that this attribute is redundant if the variable is declared constexpr. #if defined(__cpp_constinit) && __cpp_constinit >= 201907L #define ABSL_CONST_INIT constinit #elif ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) #define ABSL_CONST_INIT [[clang::require_constant_initialization]] #else #define ABSL_CONST_INIT #endif // ABSL_ATTRIBUTE_PURE_FUNCTION // // ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure" // functions. A function is pure if its return value is only a function of its // arguments. The pure attribute prohibits a function from modifying the state // of the program that is observable by means other than inspecting the // function's return value. Declaring such functions with the pure attribute // allows the compiler to avoid emitting some calls in repeated invocations of // the function with the same argument values. // // Example: // // ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t); #if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure) #define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]] #elif ABSL_HAVE_ATTRIBUTE(pure) #define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure)) #else // If the attribute isn't defined, we'll fallback to ABSL_MUST_USE_RESULT since // pure functions are useless if its return is ignored. #define ABSL_ATTRIBUTE_PURE_FUNCTION ABSL_MUST_USE_RESULT #endif // ABSL_ATTRIBUTE_CONST_FUNCTION // // ABSL_ATTRIBUTE_CONST_FUNCTION is used to annotate declarations of "const" // functions. A const function is similar to a pure function, with one // exception: Pure functions may return value that depend on a non-volatile // object that isn't provided as a function argument, while the const function // is guaranteed to return the same result given the same arguments. // // Example: // // ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d); #if defined(_MSC_VER) && !defined(__clang__) // Put the MSVC case first since MSVC seems to parse const as a C++ keyword. #define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION #elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::const) #define ABSL_ATTRIBUTE_CONST_FUNCTION [[gnu::const]] #elif ABSL_HAVE_ATTRIBUTE(const) #define ABSL_ATTRIBUTE_CONST_FUNCTION __attribute__((const)) #else // Since const functions are more restrictive pure function, we'll fallback to a // pure function if the const attribute is not handled. #define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION #endif // ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function // parameter or implicit object parameter is retained by the return value of the // annotated function (or, for a parameter of a constructor, in the value of the // constructed object). This attribute causes warnings to be produced if a // temporary object does not live long enough. // // When applied to a reference parameter, the referenced object is assumed to be // retained by the return value of the function. When applied to a non-reference // parameter (for example, a pointer or a class type), all temporaries // referenced by the parameter are assumed to be retained by the return value of // the function. // // See also the upstream documentation: // https://clang.llvm.org/docs/AttributeReference.html#lifetimebound // https://learn.microsoft.com/en-us/cpp/code-quality/c26816?view=msvc-170 #if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound) #define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] #elif ABSL_HAVE_CPP_ATTRIBUTE(msvc::lifetimebound) #define ABSL_ATTRIBUTE_LIFETIME_BOUND [[msvc::lifetimebound]] #elif ABSL_HAVE_ATTRIBUTE(lifetimebound) #define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound)) #else #define ABSL_ATTRIBUTE_LIFETIME_BOUND #endif // ABSL_INTERNAL_ATTRIBUTE_VIEW indicates that a type acts like a view i.e. a // raw (non-owning) pointer. This enables diagnoses similar to those enabled by // ABSL_ATTRIBUTE_LIFETIME_BOUND. // // See the following links for details: // https://reviews.llvm.org/D64448 // https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html #if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) #define ABSL_INTERNAL_ATTRIBUTE_VIEW [[gsl::Pointer]] #else #define ABSL_INTERNAL_ATTRIBUTE_VIEW #endif // ABSL_INTERNAL_ATTRIBUTE_OWNER indicates that a type acts like a smart // (owning) pointer. This enables diagnoses similar to those enabled by // ABSL_ATTRIBUTE_LIFETIME_BOUND. // // See the following links for details: // https://reviews.llvm.org/D64448 // https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html #if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) #define ABSL_INTERNAL_ATTRIBUTE_OWNER [[gsl::Owner]] #else #define ABSL_INTERNAL_ATTRIBUTE_OWNER #endif // ABSL_ATTRIBUTE_TRIVIAL_ABI // Indicates that a type is "trivially relocatable" -- meaning it can be // relocated without invoking the constructor/destructor, using a form of move // elision. // // From a memory safety point of view, putting aside destructor ordering, it's // safe to apply ABSL_ATTRIBUTE_TRIVIAL_ABI if an object's location // can change over the course of its lifetime: if a constructor can be run one // place, and then the object magically teleports to another place where some // methods are run, and then the object teleports to yet another place where it // is destroyed. This is notably not true for self-referential types, where the // move-constructor must keep the self-reference up to date. If the type changed // location without invoking the move constructor, it would have a dangling // self-reference. // // The use of this teleporting machinery means that the number of paired // move/destroy operations can change, and so it is a bad idea to apply this to // a type meant to count the number of moves. // // Warning: applying this can, rarely, break callers. Objects passed by value // will be destroyed at the end of the call, instead of the end of the // full-expression containing the call. In addition, it changes the ABI // of functions accepting this type by value (e.g. to pass in registers). // // See also the upstream documentation: // https://clang.llvm.org/docs/AttributeReference.html#trivial-abi // // b/321691395 - This is currently disabled in open-source builds since // compiler support differs. If system libraries compiled with GCC are mixed // with libraries compiled with Clang, types will have different ideas about // their ABI, leading to hard to debug crashes. #define ABSL_ATTRIBUTE_TRIVIAL_ABI // ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS // // Indicates a data member can be optimized to occupy no space (if it is empty) // and/or its tail padding can be used for other members. // // For code that is assured to only build with C++20 or later, prefer using // the standard attribute `[[no_unique_address]]` directly instead of this // macro. // // https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c20-no_unique_address // Current versions of MSVC have disabled `[[no_unique_address]]` since it // breaks ABI compatibility, but offers `[[msvc::no_unique_address]]` for // situations when it can be assured that it is desired. Since Abseil does not // claim ABI compatibility in mixed builds, we can offer it unconditionally. #if defined(_MSC_VER) && _MSC_VER >= 1929 #define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] #elif ABSL_HAVE_CPP_ATTRIBUTE(no_unique_address) #define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]] #else #define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS #endif // ABSL_ATTRIBUTE_UNINITIALIZED // // GCC and Clang support a flag `-ftrivial-auto-var-init=