Thanks for using Compiler Explorer
Sponsors
Jakt
C++
Ada
Analysis
Android Java
Android Kotlin
Assembly
C
C3
Carbon
C++ (Circle)
CIRCT
Clean
CMake
CMakeScript
COBOL
C++ for OpenCL
MLIR
Cppx
Cppx-Blue
Cppx-Gold
Cpp2-cppfront
Crystal
C#
CUDA C++
D
Dart
Elixir
Erlang
Fortran
F#
GLSL
Go
Haskell
HLSL
Hook
Hylo
IL
ispc
Java
Julia
Kotlin
LLVM IR
LLVM MIR
Modula-2
Nim
Objective-C
Objective-C++
OCaml
Odin
OpenCL C
Pascal
Pony
Python
Racket
Ruby
Rust
Snowball
Scala
Slang
Solidity
Spice
SPIR-V
Swift
LLVM TableGen
Toit
TypeScript Native
V
Vala
Visual Basic
Vyper
WASM
Zig
Javascript
GIMPLE
Ygen
c++ source #1
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
6502-c++ 11.1.0
ARM GCC 10.2.0
ARM GCC 10.3.0
ARM GCC 10.4.0
ARM GCC 10.5.0
ARM GCC 11.1.0
ARM GCC 11.2.0
ARM GCC 11.3.0
ARM GCC 11.4.0
ARM GCC 12.1.0
ARM GCC 12.2.0
ARM GCC 12.3.0
ARM GCC 12.4.0
ARM GCC 13.1.0
ARM GCC 13.2.0
ARM GCC 13.2.0 (unknown-eabi)
ARM GCC 13.3.0
ARM GCC 13.3.0 (unknown-eabi)
ARM GCC 14.1.0
ARM GCC 14.1.0 (unknown-eabi)
ARM GCC 14.2.0
ARM GCC 14.2.0 (unknown-eabi)
ARM GCC 4.5.4
ARM GCC 4.6.4
ARM GCC 5.4
ARM GCC 6.3.0
ARM GCC 6.4.0
ARM GCC 7.3.0
ARM GCC 7.5.0
ARM GCC 8.2.0
ARM GCC 8.5.0
ARM GCC 9.3.0
ARM GCC 9.4.0
ARM GCC 9.5.0
ARM GCC trunk
ARM gcc 10.2.1 (none)
ARM gcc 10.3.1 (2021.07 none)
ARM gcc 10.3.1 (2021.10 none)
ARM gcc 11.2.1 (none)
ARM gcc 5.4.1 (none)
ARM gcc 7.2.1 (none)
ARM gcc 8.2 (WinCE)
ARM gcc 8.3.1 (none)
ARM gcc 9.2.1 (none)
ARM msvc v19.0 (WINE)
ARM msvc v19.10 (WINE)
ARM msvc v19.14 (WINE)
ARM64 Morello gcc 10.1 Alpha 2
ARM64 gcc 10.2
ARM64 gcc 10.3
ARM64 gcc 10.4
ARM64 gcc 10.5.0
ARM64 gcc 11.1
ARM64 gcc 11.2
ARM64 gcc 11.3
ARM64 gcc 11.4.0
ARM64 gcc 12.1
ARM64 gcc 12.2.0
ARM64 gcc 12.3.0
ARM64 gcc 12.4.0
ARM64 gcc 13.1.0
ARM64 gcc 13.2.0
ARM64 gcc 13.3.0
ARM64 gcc 14.1.0
ARM64 gcc 14.2.0
ARM64 gcc 4.9.4
ARM64 gcc 5.4
ARM64 gcc 5.5.0
ARM64 gcc 6.3
ARM64 gcc 6.4
ARM64 gcc 7.3
ARM64 gcc 7.5
ARM64 gcc 8.2
ARM64 gcc 8.5
ARM64 gcc 9.3
ARM64 gcc 9.4
ARM64 gcc 9.5
ARM64 gcc trunk
ARM64 msvc v19.14 (WINE)
AVR gcc 10.3.0
AVR gcc 11.1.0
AVR gcc 12.1.0
AVR gcc 12.2.0
AVR gcc 12.3.0
AVR gcc 12.4.0
AVR gcc 13.1.0
AVR gcc 13.2.0
AVR gcc 13.3.0
AVR gcc 14.1.0
AVR gcc 14.2.0
AVR gcc 4.5.4
AVR gcc 4.6.4
AVR gcc 5.4.0
AVR gcc 9.2.0
AVR gcc 9.3.0
Arduino Mega (1.8.9)
Arduino Uno (1.8.9)
BPF clang (trunk)
BPF clang 13.0.0
BPF clang 14.0.0
BPF clang 15.0.0
BPF clang 16.0.0
BPF clang 17.0.1
BPF clang 18.1.0
BPF clang 19.1.0
EDG (experimental reflection)
EDG 6.5
EDG 6.5 (GNU mode gcc 13)
EDG 6.6
EDG 6.6 (GNU mode gcc 13)
FRC 2019
FRC 2020
FRC 2023
HPPA gcc 14.2.0
KVX ACB 4.1.0 (GCC 7.5.0)
KVX ACB 4.1.0-cd1 (GCC 7.5.0)
KVX ACB 4.10.0 (GCC 10.3.1)
KVX ACB 4.11.1 (GCC 10.3.1)
KVX ACB 4.12.0 (GCC 11.3.0)
KVX ACB 4.2.0 (GCC 7.5.0)
KVX ACB 4.3.0 (GCC 7.5.0)
KVX ACB 4.4.0 (GCC 7.5.0)
KVX ACB 4.6.0 (GCC 9.4.1)
KVX ACB 4.8.0 (GCC 9.4.1)
KVX ACB 4.9.0 (GCC 9.4.1)
KVX ACB 5.0.0 (GCC 12.2.1)
KVX ACB 5.2.0 (GCC 13.2.1)
LoongArch64 clang (trunk)
LoongArch64 clang 17.0.1
LoongArch64 clang 18.1.0
LoongArch64 clang 19.1.0
M68K gcc 13.1.0
M68K gcc 13.2.0
M68K gcc 13.3.0
M68K gcc 14.1.0
M68K gcc 14.2.0
M68k clang (trunk)
MRISC32 gcc (trunk)
MSP430 gcc 4.5.3
MSP430 gcc 5.3.0
MSP430 gcc 6.2.1
MinGW clang 14.0.3
MinGW clang 14.0.6
MinGW clang 15.0.7
MinGW clang 16.0.0
MinGW clang 16.0.2
MinGW gcc 11.3.0
MinGW gcc 12.1.0
MinGW gcc 12.2.0
MinGW gcc 13.1.0
RISC-V (32-bits) gcc (trunk)
RISC-V (32-bits) gcc 10.2.0
RISC-V (32-bits) gcc 10.3.0
RISC-V (32-bits) gcc 11.2.0
RISC-V (32-bits) gcc 11.3.0
RISC-V (32-bits) gcc 11.4.0
RISC-V (32-bits) gcc 12.1.0
RISC-V (32-bits) gcc 12.2.0
RISC-V (32-bits) gcc 12.3.0
RISC-V (32-bits) gcc 12.4.0
RISC-V (32-bits) gcc 13.1.0
RISC-V (32-bits) gcc 13.2.0
RISC-V (32-bits) gcc 13.3.0
RISC-V (32-bits) gcc 14.1.0
RISC-V (32-bits) gcc 14.2.0
RISC-V (32-bits) gcc 8.2.0
RISC-V (32-bits) gcc 8.5.0
RISC-V (32-bits) gcc 9.4.0
RISC-V (64-bits) gcc (trunk)
RISC-V (64-bits) gcc 10.2.0
RISC-V (64-bits) gcc 10.3.0
RISC-V (64-bits) gcc 11.2.0
RISC-V (64-bits) gcc 11.3.0
RISC-V (64-bits) gcc 11.4.0
RISC-V (64-bits) gcc 12.1.0
RISC-V (64-bits) gcc 12.2.0
RISC-V (64-bits) gcc 12.3.0
RISC-V (64-bits) gcc 12.4.0
RISC-V (64-bits) gcc 13.1.0
RISC-V (64-bits) gcc 13.2.0
RISC-V (64-bits) gcc 13.3.0
RISC-V (64-bits) gcc 14.1.0
RISC-V (64-bits) gcc 14.2.0
RISC-V (64-bits) gcc 8.2.0
RISC-V (64-bits) gcc 8.5.0
RISC-V (64-bits) gcc 9.4.0
RISC-V rv32gc clang (trunk)
RISC-V rv32gc clang 10.0.0
RISC-V rv32gc clang 10.0.1
RISC-V rv32gc clang 11.0.0
RISC-V rv32gc clang 11.0.1
RISC-V rv32gc clang 12.0.0
RISC-V rv32gc clang 12.0.1
RISC-V rv32gc clang 13.0.0
RISC-V rv32gc clang 13.0.1
RISC-V rv32gc clang 14.0.0
RISC-V rv32gc clang 15.0.0
RISC-V rv32gc clang 16.0.0
RISC-V rv32gc clang 17.0.1
RISC-V rv32gc clang 18.1.0
RISC-V rv32gc clang 19.1.0
RISC-V rv32gc clang 9.0.0
RISC-V rv32gc clang 9.0.1
RISC-V rv64gc clang (trunk)
RISC-V rv64gc clang 10.0.0
RISC-V rv64gc clang 10.0.1
RISC-V rv64gc clang 11.0.0
RISC-V rv64gc clang 11.0.1
RISC-V rv64gc clang 12.0.0
RISC-V rv64gc clang 12.0.1
RISC-V rv64gc clang 13.0.0
RISC-V rv64gc clang 13.0.1
RISC-V rv64gc clang 14.0.0
RISC-V rv64gc clang 15.0.0
RISC-V rv64gc clang 16.0.0
RISC-V rv64gc clang 17.0.1
RISC-V rv64gc clang 18.1.0
RISC-V rv64gc clang 19.1.0
RISC-V rv64gc clang 9.0.0
RISC-V rv64gc clang 9.0.1
Raspbian Buster
Raspbian Stretch
SPARC LEON gcc 12.2.0
SPARC LEON gcc 12.3.0
SPARC LEON gcc 12.4.0
SPARC LEON gcc 13.1.0
SPARC LEON gcc 13.2.0
SPARC LEON gcc 13.3.0
SPARC LEON gcc 14.1.0
SPARC LEON gcc 14.2.0
SPARC gcc 12.2.0
SPARC gcc 12.3.0
SPARC gcc 12.4.0
SPARC gcc 13.1.0
SPARC gcc 13.2.0
SPARC gcc 13.3.0
SPARC gcc 14.1.0
SPARC gcc 14.2.0
SPARC64 gcc 12.2.0
SPARC64 gcc 12.3.0
SPARC64 gcc 12.4.0
SPARC64 gcc 13.1.0
SPARC64 gcc 13.2.0
SPARC64 gcc 13.3.0
SPARC64 gcc 14.1.0
SPARC64 gcc 14.2.0
TI C6x gcc 12.2.0
TI C6x gcc 12.3.0
TI C6x gcc 12.4.0
TI C6x gcc 13.1.0
TI C6x gcc 13.2.0
TI C6x gcc 13.3.0
TI C6x gcc 14.1.0
TI C6x gcc 14.2.0
TI CL430 21.6.1
VAX gcc NetBSDELF 10.4.0
VAX gcc NetBSDELF 10.5.0 (Nov 15 03:50:22 2023)
WebAssembly clang (trunk)
Xtensa ESP32 gcc 11.2.0 (2022r1)
Xtensa ESP32 gcc 12.2.0 (20230208)
Xtensa ESP32 gcc 8.2.0 (2019r2)
Xtensa ESP32 gcc 8.2.0 (2020r1)
Xtensa ESP32 gcc 8.2.0 (2020r2)
Xtensa ESP32 gcc 8.4.0 (2020r3)
Xtensa ESP32 gcc 8.4.0 (2021r1)
Xtensa ESP32 gcc 8.4.0 (2021r2)
Xtensa ESP32-S2 gcc 11.2.0 (2022r1)
Xtensa ESP32-S2 gcc 12.2.0 (20230208)
Xtensa ESP32-S2 gcc 8.2.0 (2019r2)
Xtensa ESP32-S2 gcc 8.2.0 (2020r1)
Xtensa ESP32-S2 gcc 8.2.0 (2020r2)
Xtensa ESP32-S2 gcc 8.4.0 (2020r3)
Xtensa ESP32-S2 gcc 8.4.0 (2021r1)
Xtensa ESP32-S2 gcc 8.4.0 (2021r2)
Xtensa ESP32-S3 gcc 11.2.0 (2022r1)
Xtensa ESP32-S3 gcc 12.2.0 (20230208)
Xtensa ESP32-S3 gcc 8.4.0 (2020r3)
Xtensa ESP32-S3 gcc 8.4.0 (2021r1)
Xtensa ESP32-S3 gcc 8.4.0 (2021r2)
arm64 msvc v19.20 VS16.0
arm64 msvc v19.21 VS16.1
arm64 msvc v19.22 VS16.2
arm64 msvc v19.23 VS16.3
arm64 msvc v19.24 VS16.4
arm64 msvc v19.25 VS16.5
arm64 msvc v19.27 VS16.7
arm64 msvc v19.28 VS16.8
arm64 msvc v19.28 VS16.9
arm64 msvc v19.29 VS16.10
arm64 msvc v19.29 VS16.11
arm64 msvc v19.30 VS17.0
arm64 msvc v19.31 VS17.1
arm64 msvc v19.32 VS17.2
arm64 msvc v19.33 VS17.3
arm64 msvc v19.34 VS17.4
arm64 msvc v19.35 VS17.5
arm64 msvc v19.36 VS17.6
arm64 msvc v19.37 VS17.7
arm64 msvc v19.38 VS17.8
arm64 msvc v19.39 VS17.9
arm64 msvc v19.40 VS17.10
arm64 msvc v19.latest
armv7-a clang (trunk)
armv7-a clang 10.0.0
armv7-a clang 10.0.1
armv7-a clang 11.0.0
armv7-a clang 11.0.1
armv7-a clang 12.0.0
armv7-a clang 12.0.1
armv7-a clang 13.0.0
armv7-a clang 13.0.1
armv7-a clang 14.0.0
armv7-a clang 15.0.0
armv7-a clang 16.0.0
armv7-a clang 17.0.1
armv7-a clang 18.1.0
armv7-a clang 19.1.0
armv7-a clang 9.0.0
armv7-a clang 9.0.1
armv8-a clang (all architectural features, trunk)
armv8-a clang (trunk)
armv8-a clang 10.0.0
armv8-a clang 10.0.1
armv8-a clang 11.0.0
armv8-a clang 11.0.1
armv8-a clang 12.0.0
armv8-a clang 13.0.0
armv8-a clang 14.0.0
armv8-a clang 15.0.0
armv8-a clang 16.0.0
armv8-a clang 17.0.1
armv8-a clang 18.1.0
armv8-a clang 19.1.0
armv8-a clang 9.0.0
armv8-a clang 9.0.1
clang-cl 18.1.0
ellcc 0.1.33
ellcc 0.1.34
ellcc 2017-07-16
hexagon-clang 16.0.5
llvm-mos atari2600-3e
llvm-mos atari2600-4k
llvm-mos atari2600-common
llvm-mos atari5200-supercart
llvm-mos atari8-cart-megacart
llvm-mos atari8-cart-std
llvm-mos atari8-cart-xegs
llvm-mos atari8-common
llvm-mos atari8-dos
llvm-mos c128
llvm-mos c64
llvm-mos commodore
llvm-mos cpm65
llvm-mos cx16
llvm-mos dodo
llvm-mos eater
llvm-mos mega65
llvm-mos nes
llvm-mos nes-action53
llvm-mos nes-cnrom
llvm-mos nes-gtrom
llvm-mos nes-mmc1
llvm-mos nes-mmc3
llvm-mos nes-nrom
llvm-mos nes-unrom
llvm-mos nes-unrom-512
llvm-mos osi-c1p
llvm-mos pce
llvm-mos pce-cd
llvm-mos pce-common
llvm-mos pet
llvm-mos rp6502
llvm-mos rpc8e
llvm-mos supervision
llvm-mos vic20
loongarch64 gcc 12.2.0
loongarch64 gcc 12.3.0
loongarch64 gcc 12.4.0
loongarch64 gcc 13.1.0
loongarch64 gcc 13.2.0
loongarch64 gcc 13.3.0
loongarch64 gcc 14.1.0
loongarch64 gcc 14.2.0
mips clang 13.0.0
mips clang 14.0.0
mips clang 15.0.0
mips clang 16.0.0
mips clang 17.0.1
mips clang 18.1.0
mips clang 19.1.0
mips gcc 11.2.0
mips gcc 12.1.0
mips gcc 12.2.0
mips gcc 12.3.0
mips gcc 12.4.0
mips gcc 13.1.0
mips gcc 13.2.0
mips gcc 13.3.0
mips gcc 14.1.0
mips gcc 14.2.0
mips gcc 4.9.4
mips gcc 5.4
mips gcc 5.5.0
mips gcc 9.3.0 (codescape)
mips gcc 9.5.0
mips64 (el) gcc 12.1.0
mips64 (el) gcc 12.2.0
mips64 (el) gcc 12.3.0
mips64 (el) gcc 12.4.0
mips64 (el) gcc 13.1.0
mips64 (el) gcc 13.2.0
mips64 (el) gcc 13.3.0
mips64 (el) gcc 14.1.0
mips64 (el) gcc 14.2.0
mips64 (el) gcc 4.9.4
mips64 (el) gcc 5.4.0
mips64 (el) gcc 5.5.0
mips64 (el) gcc 9.5.0
mips64 clang 13.0.0
mips64 clang 14.0.0
mips64 clang 15.0.0
mips64 clang 16.0.0
mips64 clang 17.0.1
mips64 clang 18.1.0
mips64 clang 19.1.0
mips64 gcc 11.2.0
mips64 gcc 12.1.0
mips64 gcc 12.2.0
mips64 gcc 12.3.0
mips64 gcc 12.4.0
mips64 gcc 13.1.0
mips64 gcc 13.2.0
mips64 gcc 13.3.0
mips64 gcc 14.1.0
mips64 gcc 14.2.0
mips64 gcc 4.9.4
mips64 gcc 5.4.0
mips64 gcc 5.5.0
mips64 gcc 9.5.0
mips64el clang 13.0.0
mips64el clang 14.0.0
mips64el clang 15.0.0
mips64el clang 16.0.0
mips64el clang 17.0.1
mips64el clang 18.1.0
mips64el clang 19.1.0
mipsel clang 13.0.0
mipsel clang 14.0.0
mipsel clang 15.0.0
mipsel clang 16.0.0
mipsel clang 17.0.1
mipsel clang 18.1.0
mipsel clang 19.1.0
mipsel gcc 12.1.0
mipsel gcc 12.2.0
mipsel gcc 12.3.0
mipsel gcc 12.4.0
mipsel gcc 13.1.0
mipsel gcc 13.2.0
mipsel gcc 13.3.0
mipsel gcc 14.1.0
mipsel gcc 14.2.0
mipsel gcc 4.9.4
mipsel gcc 5.4.0
mipsel gcc 5.5.0
mipsel gcc 9.5.0
nanoMIPS gcc 6.3.0 (mtk)
power gcc 11.2.0
power gcc 12.1.0
power gcc 12.2.0
power gcc 12.3.0
power gcc 12.4.0
power gcc 13.1.0
power gcc 13.2.0
power gcc 13.3.0
power gcc 14.1.0
power gcc 14.2.0
power gcc 4.8.5
power64 AT12.0 (gcc8)
power64 AT13.0 (gcc9)
power64 gcc 11.2.0
power64 gcc 12.1.0
power64 gcc 12.2.0
power64 gcc 12.3.0
power64 gcc 12.4.0
power64 gcc 13.1.0
power64 gcc 13.2.0
power64 gcc 13.3.0
power64 gcc 14.1.0
power64 gcc 14.2.0
power64 gcc trunk
power64le AT12.0 (gcc8)
power64le AT13.0 (gcc9)
power64le clang (trunk)
power64le gcc 11.2.0
power64le gcc 12.1.0
power64le gcc 12.2.0
power64le gcc 12.3.0
power64le gcc 12.4.0
power64le gcc 13.1.0
power64le gcc 13.2.0
power64le gcc 13.3.0
power64le gcc 14.1.0
power64le gcc 14.2.0
power64le gcc 6.3.0
power64le gcc trunk
powerpc64 clang (trunk)
qnx 8.0.0
s390x gcc 11.2.0
s390x gcc 12.1.0
s390x gcc 12.2.0
s390x gcc 12.3.0
s390x gcc 12.4.0
s390x gcc 13.1.0
s390x gcc 13.2.0
s390x gcc 13.3.0
s390x gcc 14.1.0
s390x gcc 14.2.0
sh gcc 12.2.0
sh gcc 12.3.0
sh gcc 12.4.0
sh gcc 13.1.0
sh gcc 13.2.0
sh gcc 13.3.0
sh gcc 14.1.0
sh gcc 14.2.0
sh gcc 4.9.4
sh gcc 9.5.0
vast (trunk)
x64 msvc v19.0 (WINE)
x64 msvc v19.10 (WINE)
x64 msvc v19.14 (WINE)
x64 msvc v19.20 VS16.0
x64 msvc v19.21 VS16.1
x64 msvc v19.22 VS16.2
x64 msvc v19.23 VS16.3
x64 msvc v19.24 VS16.4
x64 msvc v19.25 VS16.5
x64 msvc v19.27 VS16.7
x64 msvc v19.28 VS16.8
x64 msvc v19.28 VS16.9
x64 msvc v19.29 VS16.10
x64 msvc v19.29 VS16.11
x64 msvc v19.30 VS17.0
x64 msvc v19.31 VS17.1
x64 msvc v19.32 VS17.2
x64 msvc v19.33 VS17.3
x64 msvc v19.34 VS17.4
x64 msvc v19.35 VS17.5
x64 msvc v19.36 VS17.6
x64 msvc v19.37 VS17.7
x64 msvc v19.38 VS17.8
x64 msvc v19.39 VS17.9
x64 msvc v19.40 VS17.10
x64 msvc v19.latest
x86 djgpp 4.9.4
x86 djgpp 5.5.0
x86 djgpp 6.4.0
x86 djgpp 7.2.0
x86 msvc v19.0 (WINE)
x86 msvc v19.10 (WINE)
x86 msvc v19.14 (WINE)
x86 msvc v19.20 VS16.0
x86 msvc v19.21 VS16.1
x86 msvc v19.22 VS16.2
x86 msvc v19.23 VS16.3
x86 msvc v19.24 VS16.4
x86 msvc v19.25 VS16.5
x86 msvc v19.27 VS16.7
x86 msvc v19.28 VS16.8
x86 msvc v19.28 VS16.9
x86 msvc v19.29 VS16.10
x86 msvc v19.29 VS16.11
x86 msvc v19.30 VS17.0
x86 msvc v19.31 VS17.1
x86 msvc v19.32 VS17.2
x86 msvc v19.33 VS17.3
x86 msvc v19.34 VS17.4
x86 msvc v19.35 VS17.5
x86 msvc v19.36 VS17.6
x86 msvc v19.37 VS17.7
x86 msvc v19.38 VS17.8
x86 msvc v19.39 VS17.9
x86 msvc v19.40 VS17.10
x86 msvc v19.latest
x86 nvc++ 22.11
x86 nvc++ 22.7
x86 nvc++ 22.9
x86 nvc++ 23.1
x86 nvc++ 23.11
x86 nvc++ 23.3
x86 nvc++ 23.5
x86 nvc++ 23.7
x86 nvc++ 23.9
x86 nvc++ 24.1
x86 nvc++ 24.11
x86 nvc++ 24.3
x86 nvc++ 24.5
x86 nvc++ 24.7
x86 nvc++ 24.9
x86-64 Zapcc 190308
x86-64 clang (Chris Bazley N3089)
x86-64 clang (EricWF contracts)
x86-64 clang (amd-staging)
x86-64 clang (assertions trunk)
x86-64 clang (clangir)
x86-64 clang (dascandy contracts)
x86-64 clang (experimental -Wlifetime)
x86-64 clang (experimental P1061)
x86-64 clang (experimental P1144)
x86-64 clang (experimental P1221)
x86-64 clang (experimental P2996)
x86-64 clang (experimental P2998)
x86-64 clang (experimental P3068)
x86-64 clang (experimental P3309)
x86-64 clang (experimental P3367)
x86-64 clang (experimental P3372)
x86-64 clang (experimental metaprogramming - P2632)
x86-64 clang (old concepts branch)
x86-64 clang (p1974)
x86-64 clang (pattern matching - P2688)
x86-64 clang (reflection)
x86-64 clang (resugar)
x86-64 clang (string interpolation - P3412)
x86-64 clang (thephd.dev)
x86-64 clang (trunk)
x86-64 clang (variadic friends - P2893)
x86-64 clang (widberg)
x86-64 clang 10.0.0
x86-64 clang 10.0.0 (assertions)
x86-64 clang 10.0.1
x86-64 clang 11.0.0
x86-64 clang 11.0.0 (assertions)
x86-64 clang 11.0.1
x86-64 clang 12.0.0
x86-64 clang 12.0.0 (assertions)
x86-64 clang 12.0.1
x86-64 clang 13.0.0
x86-64 clang 13.0.0 (assertions)
x86-64 clang 13.0.1
x86-64 clang 14.0.0
x86-64 clang 14.0.0 (assertions)
x86-64 clang 15.0.0
x86-64 clang 15.0.0 (assertions)
x86-64 clang 16.0.0
x86-64 clang 16.0.0 (assertions)
x86-64 clang 17.0.1
x86-64 clang 17.0.1 (assertions)
x86-64 clang 18.1.0
x86-64 clang 18.1.0 (assertions)
x86-64 clang 18.1.0 (clad 1.8)
x86-64 clang 19.1.0
x86-64 clang 19.1.0 (assertions)
x86-64 clang 2.6.0 (assertions)
x86-64 clang 2.7.0 (assertions)
x86-64 clang 2.8.0 (assertions)
x86-64 clang 2.9.0 (assertions)
x86-64 clang 3.0.0
x86-64 clang 3.0.0 (assertions)
x86-64 clang 3.1
x86-64 clang 3.1 (assertions)
x86-64 clang 3.2
x86-64 clang 3.2 (assertions)
x86-64 clang 3.3
x86-64 clang 3.3 (assertions)
x86-64 clang 3.4 (assertions)
x86-64 clang 3.4.1
x86-64 clang 3.5
x86-64 clang 3.5 (assertions)
x86-64 clang 3.5.1
x86-64 clang 3.5.2
x86-64 clang 3.6
x86-64 clang 3.6 (assertions)
x86-64 clang 3.7
x86-64 clang 3.7 (assertions)
x86-64 clang 3.7.1
x86-64 clang 3.8
x86-64 clang 3.8 (assertions)
x86-64 clang 3.8.1
x86-64 clang 3.9.0
x86-64 clang 3.9.0 (assertions)
x86-64 clang 3.9.1
x86-64 clang 4.0.0
x86-64 clang 4.0.0 (assertions)
x86-64 clang 4.0.1
x86-64 clang 5.0.0
x86-64 clang 5.0.0 (assertions)
x86-64 clang 5.0.1
x86-64 clang 5.0.2
x86-64 clang 6.0.0
x86-64 clang 6.0.0 (assertions)
x86-64 clang 6.0.1
x86-64 clang 7.0.0
x86-64 clang 7.0.0 (assertions)
x86-64 clang 7.0.1
x86-64 clang 7.1.0
x86-64 clang 8.0.0
x86-64 clang 8.0.0 (assertions)
x86-64 clang 8.0.1
x86-64 clang 9.0.0
x86-64 clang 9.0.0 (assertions)
x86-64 clang 9.0.1
x86-64 clang rocm-4.5.2
x86-64 clang rocm-5.0.2
x86-64 clang rocm-5.1.3
x86-64 clang rocm-5.2.3
x86-64 clang rocm-5.3.3
x86-64 clang rocm-5.7.0
x86-64 clang rocm-6.0.2
x86-64 clang rocm-6.1.2
x86-64 gcc (contract labels)
x86-64 gcc (contracts natural syntax)
x86-64 gcc (contracts)
x86-64 gcc (coroutines)
x86-64 gcc (modules)
x86-64 gcc (trunk)
x86-64 gcc 10.1
x86-64 gcc 10.2
x86-64 gcc 10.3
x86-64 gcc 10.3 (assertions)
x86-64 gcc 10.4
x86-64 gcc 10.4 (assertions)
x86-64 gcc 10.5
x86-64 gcc 10.5 (assertions)
x86-64 gcc 11.1
x86-64 gcc 11.1 (assertions)
x86-64 gcc 11.2
x86-64 gcc 11.2 (assertions)
x86-64 gcc 11.3
x86-64 gcc 11.3 (assertions)
x86-64 gcc 11.4
x86-64 gcc 11.4 (assertions)
x86-64 gcc 12.1
x86-64 gcc 12.1 (assertions)
x86-64 gcc 12.2
x86-64 gcc 12.2 (assertions)
x86-64 gcc 12.3
x86-64 gcc 12.3 (assertions)
x86-64 gcc 12.4
x86-64 gcc 12.4 (assertions)
x86-64 gcc 13.1
x86-64 gcc 13.1 (assertions)
x86-64 gcc 13.2
x86-64 gcc 13.2 (assertions)
x86-64 gcc 13.3
x86-64 gcc 13.3 (assertions)
x86-64 gcc 14.1
x86-64 gcc 14.1 (assertions)
x86-64 gcc 14.2
x86-64 gcc 14.2 (assertions)
x86-64 gcc 3.4.6
x86-64 gcc 4.0.4
x86-64 gcc 4.1.2
x86-64 gcc 4.4.7
x86-64 gcc 4.5.3
x86-64 gcc 4.6.4
x86-64 gcc 4.7.1
x86-64 gcc 4.7.2
x86-64 gcc 4.7.3
x86-64 gcc 4.7.4
x86-64 gcc 4.8.1
x86-64 gcc 4.8.2
x86-64 gcc 4.8.3
x86-64 gcc 4.8.4
x86-64 gcc 4.8.5
x86-64 gcc 4.9.0
x86-64 gcc 4.9.1
x86-64 gcc 4.9.2
x86-64 gcc 4.9.3
x86-64 gcc 4.9.4
x86-64 gcc 5.1
x86-64 gcc 5.2
x86-64 gcc 5.3
x86-64 gcc 5.4
x86-64 gcc 5.5
x86-64 gcc 6.1
x86-64 gcc 6.2
x86-64 gcc 6.3
x86-64 gcc 6.4
x86-64 gcc 6.5
x86-64 gcc 7.1
x86-64 gcc 7.2
x86-64 gcc 7.3
x86-64 gcc 7.4
x86-64 gcc 7.5
x86-64 gcc 8.1
x86-64 gcc 8.2
x86-64 gcc 8.3
x86-64 gcc 8.4
x86-64 gcc 8.5
x86-64 gcc 9.1
x86-64 gcc 9.2
x86-64 gcc 9.3
x86-64 gcc 9.4
x86-64 gcc 9.5
x86-64 icc 13.0.1
x86-64 icc 16.0.3
x86-64 icc 17.0.0
x86-64 icc 18.0.0
x86-64 icc 19.0.0
x86-64 icc 19.0.1
x86-64 icc 2021.1.2
x86-64 icc 2021.10.0
x86-64 icc 2021.2.0
x86-64 icc 2021.3.0
x86-64 icc 2021.4.0
x86-64 icc 2021.5.0
x86-64 icc 2021.6.0
x86-64 icc 2021.7.0
x86-64 icc 2021.7.1
x86-64 icc 2021.8.0
x86-64 icc 2021.9.0
x86-64 icx 2021.1.2
x86-64 icx 2021.2.0
x86-64 icx 2021.3.0
x86-64 icx 2021.4.0
x86-64 icx 2022.0.0
x86-64 icx 2022.1.0
x86-64 icx 2022.2.0
x86-64 icx 2022.2.1
x86-64 icx 2023.0.0
x86-64 icx 2023.1.0
x86-64 icx 2023.2.1
x86-64 icx 2024.0.0
x86-64 icx 2024.1.0
x86-64 icx 2024.2.0
x86-64 icx 2025.0.0
x86-64 icx 2025.0.0
zig c++ 0.10.0
zig c++ 0.11.0
zig c++ 0.12.0
zig c++ 0.12.1
zig c++ 0.13.0
zig c++ 0.6.0
zig c++ 0.7.0
zig c++ 0.7.1
zig c++ 0.8.0
zig c++ 0.9.0
zig c++ trunk
Options
Source code
#ifdef _LIBCPP_OLD_STRING // -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_STRING #define _LIBCPP_STRING // clang-format off /* string synopsis #include <compare> #include <initializer_list> namespace std { template <class stateT> class fpos { private: stateT st; public: fpos(streamoff = streamoff()); operator streamoff() const; stateT state() const; void state(stateT); fpos& operator+=(streamoff); fpos operator+ (streamoff) const; fpos& operator-=(streamoff); fpos operator- (streamoff) const; }; template <class stateT> streamoff operator-(const fpos<stateT>& x, const fpos<stateT>& y); template <class stateT> bool operator==(const fpos<stateT>& x, const fpos<stateT>& y); template <class stateT> bool operator!=(const fpos<stateT>& x, const fpos<stateT>& y); template <class charT> struct char_traits { using char_type = charT; using int_type = ...; using off_type = streamoff; using pos_type = streampos; using state_type = mbstate_t; using comparison_category = strong_ordering; // Since C++20 only for the specializations // char, wchar_t, char8_t, char16_t, and char32_t. static void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static int compare(const char_type* s1, const char_type* s2, size_t n); static size_t length(const char_type* s); static const char_type* find(const char_type* s, size_t n, const char_type& a); static char_type* move(char_type* s1, const char_type* s2, size_t n); static char_type* copy(char_type* s1, const char_type* s2, size_t n); static char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; }; template <> struct char_traits<char>; template <> struct char_traits<wchar_t>; template <> struct char_traits<char8_t>; // C++20 template <> struct char_traits<char16_t>; template <> struct char_traits<char32_t>; template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > class basic_string { public: // types: typedef traits traits_type; typedef typename traits_type::char_type value_type; typedef Allocator allocator_type; typedef typename allocator_type::size_type size_type; typedef typename allocator_type::difference_type difference_type; typedef typename allocator_type::reference reference; typedef typename allocator_type::const_reference const_reference; typedef typename allocator_type::pointer pointer; typedef typename allocator_type::const_pointer const_pointer; typedef implementation-defined iterator; typedef implementation-defined const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; static const size_type npos = -1; basic_string() noexcept(is_nothrow_default_constructible<allocator_type>::value); // constexpr since C++20 explicit basic_string(const allocator_type& a); // constexpr since C++20 basic_string(const basic_string& str); // constexpr since C++20 basic_string(basic_string&& str) noexcept(is_nothrow_move_constructible<allocator_type>::value); // constexpr since C++20 basic_string(const basic_string& str, size_type pos, const allocator_type& a = allocator_type()); // constexpr since C++20 basic_string(const basic_string& str, size_type pos, size_type n, const Allocator& a = Allocator()); // constexpr since C++20 constexpr basic_string( basic_string&& str, size_type pos, const Allocator& a = Allocator()); // since C++23 constexpr basic_string( basic_string&& str, size_type pos, size_type n, const Allocator& a = Allocator()); // since C++23 template<class T> basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); // C++17, constexpr since C++20 template <class T> explicit basic_string(const T& t, const Allocator& a = Allocator()); // C++17, constexpr since C++20 basic_string(const value_type* s, const allocator_type& a = allocator_type()); // constexpr since C++20 basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); // constexpr since C++20 basic_string(nullptr_t) = delete; // C++23 basic_string(size_type n, value_type c, const allocator_type& a = allocator_type()); // constexpr since C++20 template<class InputIterator> basic_string(InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()); // constexpr since C++20 template<container-compatible-range<charT> R> constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); // since C++23 basic_string(initializer_list<value_type>, const Allocator& = Allocator()); // constexpr since C++20 basic_string(const basic_string&, const Allocator&); // constexpr since C++20 basic_string(basic_string&&, const Allocator&); // constexpr since C++20 ~basic_string(); // constexpr since C++20 operator basic_string_view<charT, traits>() const noexcept; // constexpr since C++20 basic_string& operator=(const basic_string& str); // constexpr since C++20 template <class T> basic_string& operator=(const T& t); // C++17, constexpr since C++20 basic_string& operator=(basic_string&& str) noexcept( allocator_type::propagate_on_container_move_assignment::value || allocator_type::is_always_equal::value ); // C++17, constexpr since C++20 basic_string& operator=(const value_type* s); // constexpr since C++20 basic_string& operator=(nullptr_t) = delete; // C++23 basic_string& operator=(value_type c); // constexpr since C++20 basic_string& operator=(initializer_list<value_type>); // constexpr since C++20 iterator begin() noexcept; // constexpr since C++20 const_iterator begin() const noexcept; // constexpr since C++20 iterator end() noexcept; // constexpr since C++20 const_iterator end() const noexcept; // constexpr since C++20 reverse_iterator rbegin() noexcept; // constexpr since C++20 const_reverse_iterator rbegin() const noexcept; // constexpr since C++20 reverse_iterator rend() noexcept; // constexpr since C++20 const_reverse_iterator rend() const noexcept; // constexpr since C++20 const_iterator cbegin() const noexcept; // constexpr since C++20 const_iterator cend() const noexcept; // constexpr since C++20 const_reverse_iterator crbegin() const noexcept; // constexpr since C++20 const_reverse_iterator crend() const noexcept; // constexpr since C++20 size_type size() const noexcept; // constexpr since C++20 size_type length() const noexcept; // constexpr since C++20 size_type max_size() const noexcept; // constexpr since C++20 size_type capacity() const noexcept; // constexpr since C++20 void resize(size_type n, value_type c); // constexpr since C++20 void resize(size_type n); // constexpr since C++20 template<class Operation> constexpr void resize_and_overwrite(size_type n, Operation op); // since C++23 void reserve(size_type res_arg); // constexpr since C++20 void reserve(); // deprecated in C++20, removed in C++26 void shrink_to_fit(); // constexpr since C++20 void clear() noexcept; // constexpr since C++20 bool empty() const noexcept; // constexpr since C++20 const_reference operator[](size_type pos) const; // constexpr since C++20 reference operator[](size_type pos); // constexpr since C++20 const_reference at(size_type n) const; // constexpr since C++20 reference at(size_type n); // constexpr since C++20 basic_string& operator+=(const basic_string& str); // constexpr since C++20 template <class T> basic_string& operator+=(const T& t); // C++17, constexpr since C++20 basic_string& operator+=(const value_type* s); // constexpr since C++20 basic_string& operator+=(value_type c); // constexpr since C++20 basic_string& operator+=(initializer_list<value_type>); // constexpr since C++20 basic_string& append(const basic_string& str); // constexpr since C++20 template <class T> basic_string& append(const T& t); // C++17, constexpr since C++20 basic_string& append(const basic_string& str, size_type pos, size_type n=npos); // C++14, constexpr since C++20 template <class T> basic_string& append(const T& t, size_type pos, size_type n=npos); // C++17, constexpr since C++20 basic_string& append(const value_type* s, size_type n); // constexpr since C++20 basic_string& append(const value_type* s); // constexpr since C++20 basic_string& append(size_type n, value_type c); // constexpr since C++20 template<class InputIterator> basic_string& append(InputIterator first, InputIterator last); // constexpr since C++20 template<container-compatible-range<charT> R> constexpr basic_string& append_range(R&& rg); // C++23 basic_string& append(initializer_list<value_type>); // constexpr since C++20 void push_back(value_type c); // constexpr since C++20 void pop_back(); // constexpr since C++20 reference front(); // constexpr since C++20 const_reference front() const; // constexpr since C++20 reference back(); // constexpr since C++20 const_reference back() const; // constexpr since C++20 basic_string& assign(const basic_string& str); // constexpr since C++20 template <class T> basic_string& assign(const T& t); // C++17, constexpr since C++20 basic_string& assign(basic_string&& str); // constexpr since C++20 basic_string& assign(const basic_string& str, size_type pos, size_type n=npos); // C++14, constexpr since C++20 template <class T> basic_string& assign(const T& t, size_type pos, size_type n=npos); // C++17, constexpr since C++20 basic_string& assign(const value_type* s, size_type n); // constexpr since C++20 basic_string& assign(const value_type* s); // constexpr since C++20 basic_string& assign(size_type n, value_type c); // constexpr since C++20 template<class InputIterator> basic_string& assign(InputIterator first, InputIterator last); // constexpr since C++20 template<container-compatible-range<charT> R> constexpr basic_string& assign_range(R&& rg); // C++23 basic_string& assign(initializer_list<value_type>); // constexpr since C++20 basic_string& insert(size_type pos1, const basic_string& str); // constexpr since C++20 template <class T> basic_string& insert(size_type pos1, const T& t); // constexpr since C++20 basic_string& insert(size_type pos1, const basic_string& str, size_type pos2, size_type n); // constexpr since C++20 template <class T> basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n); // C++17, constexpr since C++20 basic_string& insert(size_type pos, const value_type* s, size_type n=npos); // C++14, constexpr since C++20 basic_string& insert(size_type pos, const value_type* s); // constexpr since C++20 basic_string& insert(size_type pos, size_type n, value_type c); // constexpr since C++20 iterator insert(const_iterator p, value_type c); // constexpr since C++20 iterator insert(const_iterator p, size_type n, value_type c); // constexpr since C++20 template<class InputIterator> iterator insert(const_iterator p, InputIterator first, InputIterator last); // constexpr since C++20 template<container-compatible-range<charT> R> constexpr iterator insert_range(const_iterator p, R&& rg); // C++23 iterator insert(const_iterator p, initializer_list<value_type>); // constexpr since C++20 basic_string& erase(size_type pos = 0, size_type n = npos); // constexpr since C++20 iterator erase(const_iterator position); // constexpr since C++20 iterator erase(const_iterator first, const_iterator last); // constexpr since C++20 basic_string& replace(size_type pos1, size_type n1, const basic_string& str); // constexpr since C++20 template <class T> basic_string& replace(size_type pos1, size_type n1, const T& t); // C++17, constexpr since C++20 basic_string& replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2=npos); // C++14, constexpr since C++20 template <class T> basic_string& replace(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n); // C++17, constexpr since C++20 basic_string& replace(size_type pos, size_type n1, const value_type* s, size_type n2); // constexpr since C++20 basic_string& replace(size_type pos, size_type n1, const value_type* s); // constexpr since C++20 basic_string& replace(size_type pos, size_type n1, size_type n2, value_type c); // constexpr since C++20 basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); // constexpr since C++20 template <class T> basic_string& replace(const_iterator i1, const_iterator i2, const T& t); // C++17, constexpr since C++20 basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s, size_type n); // constexpr since C++20 basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s); // constexpr since C++20 basic_string& replace(const_iterator i1, const_iterator i2, size_type n, value_type c); // constexpr since C++20 template<class InputIterator> basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); // constexpr since C++20 template<container-compatible-range<charT> R> constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); // C++23 basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<value_type>); // constexpr since C++20 size_type copy(value_type* s, size_type n, size_type pos = 0) const; // constexpr since C++20 basic_string substr(size_type pos = 0, size_type n = npos) const; // constexpr in C++20, removed in C++23 basic_string substr(size_type pos = 0, size_type n = npos) const&; // since C++23 constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&; // since C++23 void swap(basic_string& str) noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value || allocator_traits<allocator_type>::is_always_equal::value); // C++17, constexpr since C++20 const value_type* c_str() const noexcept; // constexpr since C++20 const value_type* data() const noexcept; // constexpr since C++20 value_type* data() noexcept; // C++17, constexpr since C++20 allocator_type get_allocator() const noexcept; // constexpr since C++20 size_type find(const basic_string& str, size_type pos = 0) const noexcept; // constexpr since C++20 template <class T> size_type find(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type find(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type find(const value_type* s, size_type pos = 0) const noexcept; // constexpr since C++20 size_type find(value_type c, size_type pos = 0) const noexcept; // constexpr since C++20 size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; // constexpr since C++20 template <class T> size_type rfind(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type rfind(const value_type* s, size_type pos = npos) const noexcept; // constexpr since C++20 size_type rfind(value_type c, size_type pos = npos) const noexcept; // constexpr since C++20 size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; // constexpr since C++20 template <class T> size_type find_first_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept; // constexpr since C++20 size_type find_first_of(value_type c, size_type pos = 0) const noexcept; // constexpr since C++20 size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept; // constexpr since C++20 template <class T> size_type find_last_of(const T& t, size_type pos = npos) const noexcept noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept; // constexpr since C++20 size_type find_last_of(value_type c, size_type pos = npos) const noexcept; // constexpr since C++20 size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept; // constexpr since C++20 template <class T> size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept; // constexpr since C++20 size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept; // constexpr since C++20 size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept; // constexpr since C++20 template <class T> size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept; // constexpr since C++20 size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept; // constexpr since C++20 int compare(const basic_string& str) const noexcept; // constexpr since C++20 template <class T> int compare(const T& t) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 int compare(size_type pos1, size_type n1, const basic_string& str) const; // constexpr since C++20 template <class T> int compare(size_type pos1, size_type n1, const T& t) const; // C++17, constexpr since C++20 int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2=npos) const; // C++14, constexpr since C++20 template <class T> int compare(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n2=npos) const; // C++17, constexpr since C++20 int compare(const value_type* s) const noexcept; // constexpr since C++20 int compare(size_type pos1, size_type n1, const value_type* s) const; // constexpr since C++20 int compare(size_type pos1, size_type n1, const value_type* s, size_type n2) const; // constexpr since C++20 constexpr bool starts_with(basic_string_view<charT, traits> sv) const noexcept; // C++20 constexpr bool starts_with(charT c) const noexcept; // C++20 constexpr bool starts_with(const charT* s) const; // C++20 constexpr bool ends_with(basic_string_view<charT, traits> sv) const noexcept; // C++20 constexpr bool ends_with(charT c) const noexcept; // C++20 constexpr bool ends_with(const charT* s) const; // C++20 constexpr bool contains(basic_string_view<charT, traits> sv) const noexcept; // C++23 constexpr bool contains(charT c) const noexcept; // C++23 constexpr bool contains(const charT* s) const; // C++23 }; template<class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>> basic_string(InputIterator, InputIterator, Allocator = Allocator()) -> basic_string<typename iterator_traits<InputIterator>::value_type, char_traits<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17 template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> basic_string(from_range_t, R&&, Allocator = Allocator()) -> basic_string<ranges::range_value_t<R>, char_traits<ranges::range_value_t<R>>, Allocator>; // C++23 template<class charT, class traits, class Allocator = allocator<charT>> explicit basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator()) -> basic_string<charT, traits, Allocator>; // C++17 template<class charT, class traits, class Allocator = allocator<charT>> basic_string(basic_string_view<charT, traits>, typename see below::size_type, typename see below::size_type, const Allocator& = Allocator()) -> basic_string<charT, traits, Allocator>; // C++17 template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs); // constexpr since C++20 template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const charT* lhs , const basic_string<charT,traits,Allocator>&rhs); // constexpr since C++20 template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(charT lhs, const basic_string<charT,traits,Allocator>& rhs); // constexpr since C++20 template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs); // constexpr since C++20 template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs); // constexpr since C++20 template<class charT, class traits, class Allocator> bool operator==(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // constexpr since C++20 template<class charT, class traits, class Allocator> bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator==(const basic_string<charT,traits,Allocator>& lhs, const charT* rhs) noexcept; // constexpr since C++20 template<class charT, class traits, class Allocator> bool operator!=(const basic_string<charT,traits,Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator!=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator!=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator< (const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator< (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator< (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator> (const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator> (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator> (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator<=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator>=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> // since C++20 constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; template<class charT, class traits, class Allocator> // since C++20 constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; template<class charT, class traits, class Allocator> void swap(basic_string<charT, traits, Allocator>& lhs, basic_string<charT, traits, Allocator>& rhs) noexcept(noexcept(lhs.swap(rhs))); // constexpr since C++20 template<class charT, class traits, class Allocator> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str); template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str); template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str, charT delim); template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str); template<class charT, class traits, class Allocator, class U> typename basic_string<charT, traits, Allocator>::size_type erase(basic_string<charT, traits, Allocator>& c, const U& value); // C++20 template<class charT, class traits, class Allocator, class Predicate> typename basic_string<charT, traits, Allocator>::size_type erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20 typedef basic_string<char> string; typedef basic_string<wchar_t> wstring; typedef basic_string<char8_t> u8string; // C++20 typedef basic_string<char16_t> u16string; typedef basic_string<char32_t> u32string; int stoi (const string& str, size_t* idx = nullptr, int base = 10); long stol (const string& str, size_t* idx = nullptr, int base = 10); unsigned long stoul (const string& str, size_t* idx = nullptr, int base = 10); long long stoll (const string& str, size_t* idx = nullptr, int base = 10); unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10); float stof (const string& str, size_t* idx = nullptr); double stod (const string& str, size_t* idx = nullptr); long double stold(const string& str, size_t* idx = nullptr); string to_string(int val); string to_string(unsigned val); string to_string(long val); string to_string(unsigned long val); string to_string(long long val); string to_string(unsigned long long val); string to_string(float val); string to_string(double val); string to_string(long double val); int stoi (const wstring& str, size_t* idx = nullptr, int base = 10); long stol (const wstring& str, size_t* idx = nullptr, int base = 10); unsigned long stoul (const wstring& str, size_t* idx = nullptr, int base = 10); long long stoll (const wstring& str, size_t* idx = nullptr, int base = 10); unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10); float stof (const wstring& str, size_t* idx = nullptr); double stod (const wstring& str, size_t* idx = nullptr); long double stold(const wstring& str, size_t* idx = nullptr); wstring to_wstring(int val); wstring to_wstring(unsigned val); wstring to_wstring(long val); wstring to_wstring(unsigned long val); wstring to_wstring(long long val); wstring to_wstring(unsigned long long val); wstring to_wstring(float val); wstring to_wstring(double val); wstring to_wstring(long double val); template <> struct hash<string>; template <> struct hash<u8string>; // C++20 template <> struct hash<u16string>; template <> struct hash<u32string>; template <> struct hash<wstring>; basic_string<char> operator""s( const char *str, size_t len ); // C++14, constexpr since C++20 basic_string<wchar_t> operator""s( const wchar_t *str, size_t len ); // C++14, constexpr since C++20 constexpr basic_string<char8_t> operator""s( const char8_t *str, size_t len ); // C++20 basic_string<char16_t> operator""s( const char16_t *str, size_t len ); // C++14, constexpr since C++20 basic_string<char32_t> operator""s( const char32_t *str, size_t len ); // C++14, constexpr since C++20 } // std */ // clang-format on #include <__algorithm/max.h> #include <__algorithm/min.h> #include <__algorithm/remove.h> #include <__algorithm/remove_if.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__format/enable_insertable.h> #include <__functional/hash.h> #include <__functional/unary_function.h> #include <__fwd/string.h> #include <__ios/fpos.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> #include <__iterator/wrap_iter.h> #include <__memory/addressof.h> #include <__memory/allocate_at_least.h> #include <__memory/allocator.h> #include <__memory/allocator_traits.h> #include <__memory/compressed_pair.h> #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> #include <__memory/swap_allocator.h> #include <__memory_resource/polymorphic_allocator.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/container_compatible_range.h> #include <__ranges/from_range.h> #include <__ranges/size.h> #include <__string/char_traits.h> #include <__string/extern_template_lists.h> #include <__type_traits/is_allocator.h> #include <__type_traits/is_array.h> #include <__type_traits/is_convertible.h> #include <__type_traits/is_nothrow_default_constructible.h> #include <__type_traits/is_nothrow_move_assignable.h> #include <__type_traits/is_same.h> #include <__type_traits/is_standard_layout.h> #include <__type_traits/is_trivial.h> #include <__type_traits/noexcept_move_assign_container.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/void_t.h> #include <__utility/auto_cast.h> #include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/is_pointer_in_range.h> #include <__utility/move.h> #include <__utility/swap.h> #include <__utility/unreachable.h> #include <climits> #include <cstdio> // EOF #include <cstring> #include <limits> #include <stdexcept> #include <string_view> #include <version> #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS # include <cwchar> #endif // standard-mandated includes // [iterator.range] #include <__iterator/access.h> #include <__iterator/data.h> #include <__iterator/empty.h> #include <__iterator/reverse_access.h> #include <__iterator/size.h> // [string.syn] #include <compare> #include <initializer_list> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD // basic_string template<class _CharT, class _Traits, class _Allocator> basic_string<_CharT, _Traits, _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const basic_string<_CharT, _Traits, _Allocator>& __y); template<class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const _CharT* __x, const basic_string<_CharT,_Traits,_Allocator>& __y); template<class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(_CharT __x, const basic_string<_CharT,_Traits,_Allocator>& __y); template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const _CharT* __y); template<class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, _CharT __y); extern template _LIBCPP_EXPORTED_FROM_ABI string operator+ <char, char_traits<char>, allocator<char> >(char const*, string const&); template <class _Iter> struct __string_is_trivial_iterator : public false_type {}; template <class _Tp> struct __string_is_trivial_iterator<_Tp*> : public is_arithmetic<_Tp> {}; template <class _Iter> struct __string_is_trivial_iterator<__wrap_iter<_Iter> > : public __string_is_trivial_iterator<_Iter> {}; template <class _CharT, class _Traits, class _Tp> struct __can_be_converted_to_string_view : public _BoolConstant< is_convertible<const _Tp&, basic_string_view<_CharT, _Traits> >::value && !is_convertible<const _Tp&, const _CharT*>::value > {}; struct __uninitialized_size_tag {}; struct __init_with_sentinel_tag {}; template<class _CharT, class _Traits, class _Allocator> class basic_string { public: typedef basic_string __self; typedef basic_string_view<_CharT, _Traits> __self_view; typedef _Traits traits_type; typedef _CharT value_type; typedef _Allocator allocator_type; typedef allocator_traits<allocator_type> __alloc_traits; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; static_assert((!is_array<value_type>::value), "Character type of basic_string must not be an array"); static_assert(( is_standard_layout<value_type>::value), "Character type of basic_string must be standard-layout"); static_assert(( is_trivial<value_type>::value), "Character type of basic_string must be trivial"); static_assert(( is_same<_CharT, typename traits_type::char_type>::value), "traits_type::char_type must be the same type as CharT"); static_assert(( is_same<typename allocator_type::value_type, value_type>::value), "Allocator::value_type must be same type as value_type"); static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value, "[allocator.requirements] states that rebinding an allocator to the same type should result in the " "original allocator"); // TODO: Implement iterator bounds checking without requiring the global database. typedef __wrap_iter<pointer> iterator; typedef __wrap_iter<const_pointer> const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; private: static_assert(CHAR_BIT == 8, "This implementation assumes that one byte contains 8 bits"); #ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT struct __long { pointer __data_; size_type __size_; size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1; size_type __is_long_ : 1; }; enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? (sizeof(__long) - 1)/sizeof(value_type) : 2}; struct __short { value_type __data_[__min_cap]; unsigned char __padding_[sizeof(value_type) - 1]; unsigned char __size_ : 7; unsigned char __is_long_ : 1; }; // The __endian_factor is required because the field we use to store the size // has one fewer bit than it would if it were not a bitfield. // // If the LSB is used to store the short-flag in the short string representation, // we have to multiply the size by two when it is stored and divide it by two when // it is loaded to make sure that we always store an even number. In the long string // representation, we can ignore this because we can assume that we always allocate // an even amount of value_types. // // If the MSB is used for the short-flag, the max_size() is numeric_limits<size_type>::max() / 2. // This does not impact the short string representation, since we never need the MSB // for representing the size of a short string anyway. #ifdef _LIBCPP_BIG_ENDIAN static const size_type __endian_factor = 2; #else static const size_type __endian_factor = 1; #endif #else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT #ifdef _LIBCPP_BIG_ENDIAN static const size_type __endian_factor = 1; #else static const size_type __endian_factor = 2; #endif // Attribute 'packed' is used to keep the layout compatible with the // previous definition that did not use bit fields. This is because on // some platforms bit fields have a default size rather than the actual // size used, e.g., it is 4 bytes on AIX. See D128285 for details. struct __long { struct _LIBCPP_PACKED { size_type __is_long_ : 1; size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1; }; size_type __size_; pointer __data_; }; enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? (sizeof(__long) - 1)/sizeof(value_type) : 2}; struct __short { struct _LIBCPP_PACKED { unsigned char __is_long_ : 1; unsigned char __size_ : 7; }; char __padding_[sizeof(value_type) - 1]; value_type __data_[__min_cap]; }; #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size."); union __ulx{__long __lx; __short __lxx;}; enum {__n_words = sizeof(__ulx) / sizeof(size_type)}; struct __raw { size_type __words[__n_words]; }; struct __rep { union { __short __s; __long __l; __raw __r; }; }; __compressed_pair<__rep, allocator_type> __r_; // Construct a string with the given allocator and enough storage to hold `__size` characters, but // don't initialize the characters. The contents of the string, including the null terminator, must be // initialized separately. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(__uninitialized_size_tag, size_type __size, const allocator_type& __a) : __r_(__default_init_tag(), __a) { if (__size > max_size()) __throw_length_error(); if (__fits_in_sso(__size)) { __r_.first() = __rep(); __set_short_size(__size); } else { auto __capacity = __recommend(__size) + 1; auto __allocation = __alloc_traits::allocate(__alloc(), __capacity); __begin_lifetime(__allocation, __capacity); __set_long_cap(__capacity); __set_long_pointer(__allocation); __set_long_size(__size); } } template <class _Iter, class _Sent> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(__init_with_sentinel_tag, _Iter __first, _Sent __last, const allocator_type& __a) : __r_(__default_init_tag(), __a) { __init_with_sentinel(std::move(__first), std::move(__last)); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __make_iterator(pointer __p) { return iterator(__p); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator __make_const_iterator(const_pointer __p) const { return const_iterator(__p); } public: _LIBCPP_TEMPLATE_DATA_VIS static const size_type npos = -1; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) : __r_(__value_init_tag(), __default_init_tag()) {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value) #else _NOEXCEPT #endif : __r_(__value_init_tag(), __a) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str) : __r_(__default_init_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc())) { if (!__str.__is_long()) __r_.first() = __str.__r_.first(); else __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str, const allocator_type& __a) : __r_(__default_init_tag(), __a) { if (!__str.__is_long()) __r_.first() = __str.__r_.first(); else __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str) # if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value) # else _NOEXCEPT # endif : __r_(std::move(__str.__r_)) { __str.__r_.first() = __rep(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str, const allocator_type& __a) : __r_(__default_init_tag(), __a) { if (__str.__is_long() && __a != __str.__alloc()) // copy, not move __init(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); else { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); __r_.first() = __str.__r_.first(); __str.__r_.first() = __rep(); } } #endif // _LIBCPP_CXX03_LANG template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s) : __r_(__default_init_tag(), __default_init_tag()) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "basic_string(const char*) detected nullptr"); __init(__s, traits_type::length(__s)); } template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, const _Allocator& __a) : __r_(__default_init_tag(), __a) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "basic_string(const char*, allocator) detected nullptr"); __init(__s, traits_type::length(__s)); } #if _LIBCPP_STD_VER >= 23 basic_string(nullptr_t) = delete; #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n) : __r_(__default_init_tag(), __default_init_tag()) { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr"); __init(__s, __n); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n, const _Allocator& __a) : __r_(__default_init_tag(), __a) { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr"); __init(__s, __n); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c) : __r_(__default_init_tag(), __default_init_tag()) { __init(__n, __c); } #if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr basic_string(basic_string&& __str, size_type __pos, const _Allocator& __alloc = _Allocator()) : basic_string(std::move(__str), __pos, npos, __alloc) {} _LIBCPP_HIDE_FROM_ABI constexpr basic_string(basic_string&& __str, size_type __pos, size_type __n, const _Allocator& __alloc = _Allocator()) : __r_(__default_init_tag(), __alloc) { if (__pos > __str.size()) __throw_out_of_range(); auto __len = std::min<size_type>(__n, __str.size() - __pos); if (__alloc_traits::is_always_equal::value || __alloc == __str.__alloc()) { __move_assign(std::move(__str), __pos, __len); } else { // Perform a copy because the allocators are not compatible. __init(__str.data() + __pos, __len); } } #endif template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c, const _Allocator& __a) : __r_(__default_init_tag(), __a) { __init(__n, __c); } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Allocator& __a = _Allocator()) : __r_(__default_init_tag(), __a) { size_type __str_sz = __str.size(); if (__pos > __str_sz) __throw_out_of_range(); __init(__str.data() + __pos, std::min(__n, __str_sz - __pos)); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a = _Allocator()) : __r_(__default_init_tag(), __a) { size_type __str_sz = __str.size(); if (__pos > __str_sz) __throw_out_of_range(); __init(__str.data() + __pos, __str_sz - __pos); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type()) : __r_(__default_init_tag(), __a) { __self_view __sv0 = __t; __self_view __sv = __sv0.substr(__pos, __n); __init(__sv.data(), __sv.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t) : __r_(__default_init_tag(), __default_init_tag()) { __self_view __sv = __t; __init(__sv.data(), __sv.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string( const _Tp& __t, const allocator_type& __a) : __r_(__default_init_tag(), __a) { __self_view __sv = __t; __init(__sv.data(), __sv.size()); } template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(_InputIterator __first, _InputIterator __last) : __r_(__default_init_tag(), __default_init_tag()) { __init(__first, __last); } template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : __r_(__default_init_tag(), __a) { __init(__first, __last); } #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> _LIBCPP_HIDE_FROM_ABI constexpr basic_string(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type()) : __r_(__default_init_tag(), __a) { if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { __init_with_size(ranges::begin(__range), ranges::end(__range), ranges::distance(__range)); } else { __init_with_sentinel(ranges::begin(__range), ranges::end(__range)); } } #endif #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il) : __r_(__default_init_tag(), __default_init_tag()) { __init(__il.begin(), __il.end()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il, const _Allocator& __a) : __r_(__default_init_tag(), __a) { __init(__il.begin(), __il.end()); } #endif // _LIBCPP_CXX03_LANG inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string() { if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const basic_string& __str); template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const _Tp& __t) { __self_view __sv = __t; return assign(__sv); } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(basic_string&& __str) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) { __move_assign(__str, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>()); return *this; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(initializer_list<value_type> __il) {return assign(__il.begin(), __il.size());} #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const value_type* __s) {return assign(__s);} #if _LIBCPP_STD_VER >= 23 basic_string& operator=(nullptr_t) = delete; #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() _NOEXCEPT {return __make_iterator(__get_pointer());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator begin() const _NOEXCEPT {return __make_const_iterator(__get_pointer());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() _NOEXCEPT {return __make_iterator(__get_pointer() + size());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator end() const _NOEXCEPT {return __make_const_iterator(__get_pointer() + size());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cbegin() const _NOEXCEPT {return begin();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cend() const _NOEXCEPT {return end();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crend() const _NOEXCEPT {return rend();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type size() const _NOEXCEPT {return __is_long() ? __get_long_size() : __get_short_size();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type length() const _NOEXCEPT {return size();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type max_size() const _NOEXCEPT { size_type __m = __alloc_traits::max_size(__alloc()); if (__m <= std::numeric_limits<size_type>::max() / 2) { return __m - __alignment; } else { bool __uses_lsb = __endian_factor == 2; return __uses_lsb ? __m - __alignment : (__m / 2) - __alignment; } } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type capacity() const _NOEXCEPT { return (__is_long() ? __get_long_cap() : static_cast<size_type>(__min_cap)) - 1; } _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __n, value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __n) { resize(__n, value_type()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 void reserve(size_type __requested_capacity); #if _LIBCPP_STD_VER >= 23 template <class _Op> _LIBCPP_HIDE_FROM_ABI constexpr void resize_and_overwrite(size_type __n, _Op __op) { __resize_default_init(__n); __erase_to_end(std::move(__op)(data(), _LIBCPP_AUTO_CAST(__n))); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __resize_default_init(size_type __n); #if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_STRING_RESERVE) _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve() _NOEXCEPT { shrink_to_fit(); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void shrink_to_fit() _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void clear() _NOEXCEPT; _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool empty() const _NOEXCEPT {return size() == 0;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds"); if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) { return *(__get_long_pointer() + __pos); } return *(data() + __pos); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __pos) _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds"); if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) { return *(__get_long_pointer() + __pos); } return *(__get_pointer() + __pos); } _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference at(size_type __n) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 reference at(size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const basic_string& __str) { return append(__str); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string >::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const _Tp& __t) { __self_view __sv = __t; return append(__sv); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const value_type* __s) { return append(__s); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(value_type __c) { push_back(__c); return *this; } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(initializer_list<value_type> __il) { return append(__il); } #endif // _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const basic_string& __str) { return append(__str.data(), __str.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const _Tp& __t) { __self_view __sv = __t; return append(__sv.data(), __sv.size()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const basic_string& __str, size_type __pos, size_type __n=npos); template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const _Tp& __t, size_type __pos, size_type __n = npos); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(size_type __n, value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __append_default_init(size_type __n); template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(_InputIterator __first, _InputIterator __last) { const basic_string __temp(__first, __last, __alloc()); append(__temp.data(), __temp.size()); return *this; } template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(_ForwardIterator __first, _ForwardIterator __last); #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> _LIBCPP_HIDE_FROM_ABI constexpr basic_string& append_range(_Range&& __range) { insert_range(end(), std::forward<_Range>(__range)); return *this; } #endif #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(initializer_list<value_type> __il) {return append(__il.begin(), __il.size());} #endif // _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back(); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty"); return *__get_pointer(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty"); return *data(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty"); return *(__get_pointer() + size() - 1); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty"); return *(data() + size() - 1); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const _Tp& __t) { __self_view __sv = __t; return assign(__sv.data(), __sv.size()); } #if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr void __move_assign(basic_string&& __str, size_type __pos, size_type __len) { // Pilfer the allocation from __str. _LIBCPP_ASSERT_INTERNAL(__alloc() == __str.__alloc(), "__move_assign called with wrong allocator"); __r_.first() = __str.__r_.first(); __str.__r_.first() = __rep(); _Traits::move(data(), data() + __pos, __len); __set_size(__len); _Traits::assign(data()[__len], value_type()); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const basic_string& __str) { return *this = __str; } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(basic_string&& __str) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) {*this = std::move(__str); return *this;} #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const basic_string& __str, size_type __pos, size_type __n=npos); template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const _Tp& __t, size_type __pos, size_type __n = npos); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(size_type __n, value_type __c); template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(_InputIterator __first, _InputIterator __last); template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(_ForwardIterator __first, _ForwardIterator __last); #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> _LIBCPP_HIDE_FROM_ABI constexpr basic_string& assign_range(_Range&& __range) { if constexpr (__string_is_trivial_iterator<ranges::iterator_t<_Range>>::value && (ranges::forward_range<_Range> || ranges::sized_range<_Range>)) { size_type __n = static_cast<size_type>(ranges::distance(__range)); __assign_trivial(ranges::begin(__range), ranges::end(__range), __n); } else { __assign_with_sentinel(ranges::begin(__range), ranges::end(__range)); } return *this; } #endif #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(initializer_list<value_type> __il) {return assign(__il.begin(), __il.size());} #endif // _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const basic_string& __str) { return insert(__pos1, __str.data(), __str.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const _Tp& __t) { __self_view __sv = __t; return insert(__pos1, __sv.data(), __sv.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n = npos); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n = npos); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, size_type __n, value_type __c); _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, value_type __c); #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> _LIBCPP_HIDE_FROM_ABI constexpr iterator insert_range(const_iterator __position, _Range&& __range) { if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { auto __n = static_cast<size_type>(ranges::distance(__range)); return __insert_with_size(__position, ranges::begin(__range), ranges::end(__range), __n); } else { basic_string __temp(from_range, std::forward<_Range>(__range), __alloc()); return insert(__position, __temp.data(), __temp.data() + __temp.size()); } } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, size_type __n, value_type __c) { difference_type __p = __pos - begin(); insert(static_cast<size_type>(__p), __n, __c); return begin() + __p; } template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, _InputIterator __first, _InputIterator __last); template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, initializer_list<value_type> __il) {return insert(__pos, __il.begin(), __il.end());} #endif // _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& erase(size_type __pos = 0, size_type __n = npos); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator erase(const_iterator __pos); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator erase(const_iterator __first, const_iterator __last); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str) { return replace(__pos1, __n1, __str.data(), __str.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos1, size_type __n1, const _Tp& __t) { __self_view __sv = __t; return replace(__pos1, __n1, __sv.data(), __sv.size()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos); template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const basic_string& __str) { return replace( static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __str.data(), __str.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) { __self_view __sv = __t; return replace(__i1 - begin(), __i2 - __i1, __sv); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n) { return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __s, __n); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const value_type* __s) { return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __s); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c) { return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __n, __c); } template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2); #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> _LIBCPP_HIDE_FROM_ABI constexpr basic_string& replace_with_range(const_iterator __i1, const_iterator __i2, _Range&& __range) { basic_string __temp(from_range, std::forward<_Range>(__range), __alloc()); return replace(__i1, __i2, __temp); } #endif #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, initializer_list<value_type> __il) {return replace(__i1, __i2, __il.begin(), __il.end());} #endif // _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const; #if _LIBCPP_STD_VER <= 20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string substr(size_type __pos = 0, size_type __n = npos) const { return basic_string(*this, __pos, __n); } #else _LIBCPP_HIDE_FROM_ABI constexpr basic_string substr(size_type __pos = 0, size_type __n = npos) const& { return basic_string(*this, __pos, __n); } _LIBCPP_HIDE_FROM_ABI constexpr basic_string substr(size_type __pos = 0, size_type __n = npos) && { return basic_string(std::move(*this), __pos, __n); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(basic_string& __str) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value); #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* c_str() const _NOEXCEPT {return data();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* data() const _NOEXCEPT {return std::__to_address(__get_pointer());} #if _LIBCPP_STD_VER >= 17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 value_type* data() _NOEXCEPT {return std::__to_address(__get_pointer());} #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator_type get_allocator() const _NOEXCEPT {return __alloc();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(value_type __c, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(value_type __c, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(value_type __c, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(value_type __c, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(value_type __c, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(value_type __c, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const basic_string& __str) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const _Tp& __t) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const _Tp& __t) const; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const basic_string& __str) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos) const; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const value_type* __s) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const value_type* __s) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const; #if _LIBCPP_STD_VER >= 20 constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(__self_view __sv) const noexcept { return __self_view(data(), size()).starts_with(__sv); } constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(value_type __c) const noexcept { return !empty() && _Traits::eq(front(), __c); } constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(const value_type* __s) const noexcept { return starts_with(__self_view(__s)); } constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(__self_view __sv) const noexcept { return __self_view(data(), size()).ends_with( __sv); } constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(value_type __c) const noexcept { return !empty() && _Traits::eq(back(), __c); } constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(const value_type* __s) const noexcept { return ends_with(__self_view(__s)); } #endif #if _LIBCPP_STD_VER >= 23 constexpr _LIBCPP_HIDE_FROM_ABI bool contains(__self_view __sv) const noexcept { return __self_view(data(), size()).contains(__sv); } constexpr _LIBCPP_HIDE_FROM_ABI bool contains(value_type __c) const noexcept { return __self_view(data(), size()).contains(__c); } constexpr _LIBCPP_HIDE_FROM_ABI bool contains(const value_type* __s) const { return __self_view(data(), size()).contains(__s); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __invariants() const; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __clear_and_shrink() _NOEXCEPT; private: template<class _Alloc> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool friend operator==(const basic_string<char, char_traits<char>, _Alloc>& __lhs, const basic_string<char, char_traits<char>, _Alloc>& __rhs) _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __shrink_or_extend(size_type __target_capacity); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_long() const _NOEXCEPT { if (__libcpp_is_constant_evaluated() && __builtin_constant_p(__r_.first().__l.__is_long_)) { return __r_.first().__l.__is_long_; } return __r_.first().__s.__is_long_; } static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __begin_lifetime(pointer __begin, size_type __n) { #if _LIBCPP_STD_VER >= 20 if (__libcpp_is_constant_evaluated()) { for (size_type __i = 0; __i != __n; ++__i) std::construct_at(std::addressof(__begin[__i])); } #else (void)__begin; (void)__n; #endif // _LIBCPP_STD_VER >= 20 } _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI static bool __fits_in_sso(size_type __sz) { return __sz < __min_cap; } template <class _Iterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign_trivial(_Iterator __first, _Sentinel __last, size_type __n); template <class _Iterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_Iterator __first, _Sentinel __last); template <class _ForwardIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 iterator __insert_from_safe_copy(size_type __n, size_type __ip, _ForwardIterator __first, _Sentinel __last) { size_type __sz = size(); size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) traits_type::move(__p + __ip + __n, __p + __ip, __n_move); } else { __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __ip, 0, __n); __p = std::__to_address(__get_long_pointer()); } __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); for (__p += __ip; __first != __last; ++__p, ++__first) traits_type::assign(*__p, *__first); return begin() + __ip; } template<class _Iterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __insert_with_size(const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 allocator_type& __alloc() _NOEXCEPT { return __r_.second(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const allocator_type& __alloc() const _NOEXCEPT { return __r_.second(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_short_size(size_type __s) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL( __s < __min_cap, "__s should never be greater than or equal to the short string capacity"); __r_.first().__s.__size_ = __s; __r_.first().__s.__is_long_ = false; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_short_size() const _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL( !__r_.first().__s.__is_long_, "String has to be short when trying to get the short size"); return __r_.first().__s.__size_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_size(size_type __s) _NOEXCEPT {__r_.first().__l.__size_ = __s;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_long_size() const _NOEXCEPT {return __r_.first().__l.__size_;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_size(size_type __s) _NOEXCEPT {if (__is_long()) __set_long_size(__s); else __set_short_size(__s);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_cap(size_type __s) _NOEXCEPT { __r_.first().__l.__cap_ = __s / __endian_factor; __r_.first().__l.__is_long_ = true; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_long_cap() const _NOEXCEPT { return __r_.first().__l.__cap_ * __endian_factor; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_pointer(pointer __p) _NOEXCEPT {__r_.first().__l.__data_ = __p;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_long_pointer() _NOEXCEPT {return __r_.first().__l.__data_;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_long_pointer() const _NOEXCEPT {return __r_.first().__l.__data_;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_short_pointer() _NOEXCEPT {return pointer_traits<pointer>::pointer_to(__r_.first().__s.__data_[0]);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_short_pointer() const _NOEXCEPT {return pointer_traits<const_pointer>::pointer_to(__r_.first().__s.__data_[0]);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_pointer() _NOEXCEPT {return __is_long() ? __get_long_pointer() : __get_short_pointer();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_pointer() const _NOEXCEPT {return __is_long() ? __get_long_pointer() : __get_short_pointer();} template <size_type __a> static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __align_it(size_type __s) _NOEXCEPT {return (__s + (__a-1)) & ~(__a-1);} enum { __alignment = #ifdef _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT 8 #else 16 #endif }; static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __recommend(size_type __s) _NOEXCEPT { if (__s < __min_cap) { return static_cast<size_type>(__min_cap) - 1; } size_type __guess = __align_it<sizeof(value_type) < __alignment ? __alignment/sizeof(value_type) : 1 > (__s+1) - 1; if (__guess == __min_cap) ++__guess; return __guess; } inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(const value_type* __s, size_type __sz, size_type __reserve); inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(const value_type* __s, size_type __sz); inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(size_type __n, value_type __c); // Slow path for the (inlined) copy constructor for 'long' strings. // Always externally instantiated and not inlined. // Requires that __s is zero terminated. // The main reason for this function to exist is because for unstable, we // want to allow inlining of the copy constructor. However, we don't want // to call the __init() functions as those are marked as inline which may // result in over-aggressive inlining by the compiler, where our aim is // to only inline the fast path code directly in the ctor. _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void __init_copy_ctor_external(const value_type* __s, size_type __sz); template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(_InputIterator __first, _InputIterator __last); template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(_ForwardIterator __first, _ForwardIterator __last); template <class _InputIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init_with_sentinel(_InputIterator __first, _Sentinel __last); template <class _InputIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init_with_size(_InputIterator __first, _Sentinel __last, size_type __sz); _LIBCPP_CONSTEXPR_SINCE_CXX20 #if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1 _LIBCPP_HIDE_FROM_ABI #endif _LIBCPP_DEPRECATED_("use __grow_by_without_replace") void __grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add = 0); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __grow_by_without_replace(size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add = 0); _LIBCPP_CONSTEXPR_SINCE_CXX20 void __grow_by_and_replace(size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add, const value_type* __p_new_stuff); // __assign_no_alias is invoked for assignment operations where we // have proof that the input does not alias the current instance. // For example, operator=(basic_string) performs a 'self' check. template <bool __is_short> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_no_alias(const value_type* __s, size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __erase_to_end(size_type __pos) { __null_terminate_at(std::__to_address(__get_pointer()), __pos); } // __erase_external_with_move is invoked for erase() invocations where // `n ~= npos`, likely requiring memory moves on the string data. _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void __erase_external_with_move(size_type __pos, size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const basic_string& __str) {__copy_assign_alloc(__str, integral_constant<bool, __alloc_traits::propagate_on_container_copy_assignment::value>());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const basic_string& __str, true_type) { if (__alloc() == __str.__alloc()) __alloc() = __str.__alloc(); else { if (!__str.__is_long()) { __clear_and_shrink(); __alloc() = __str.__alloc(); } else { allocator_type __a = __str.__alloc(); auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap()); __begin_lifetime(__allocation.ptr, __allocation.count); if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); __alloc() = std::move(__a); __set_long_pointer(__allocation.ptr); __set_long_cap(__allocation.count); __set_long_size(__str.size()); } } } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const basic_string&, false_type) _NOEXCEPT {} #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign(basic_string& __str, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign(basic_string& __str, true_type) #if _LIBCPP_STD_VER >= 17 _NOEXCEPT; #else _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value); #endif #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(basic_string& __str) _NOEXCEPT_( !__alloc_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable<allocator_type>::value) {__move_assign_alloc(__str, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>());} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(basic_string& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) { __alloc() = std::move(__c.__alloc()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(basic_string&, false_type) _NOEXCEPT {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_external(const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_external(const value_type* __s, size_type __n); // Assigns the value in __s, guaranteed to be __n < __min_cap in length. inline _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __assign_short(const value_type* __s, size_type __n) { pointer __p = __is_long() ? (__set_long_size(__n), __get_long_pointer()) : (__set_short_size(__n), __get_short_pointer()); traits_type::move(std::__to_address(__p), __s, __n); traits_type::assign(__p[__n], value_type()); return *this; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __null_terminate_at(value_type* __p, size_type __newsz) { __set_size(__newsz); traits_type::assign(__p[__newsz], value_type()); return *this; } template <class _Tp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __addr_in_range(const _Tp& __v) const { return std::__is_pointer_in_range(data(), data() + size() + 1, std::addressof(__v)); } _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_length_error() const { std::__throw_length_error("basic_string"); } _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("basic_string"); } friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+<>(const basic_string&, const basic_string&); friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+<>(const value_type*, const basic_string&); friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+<>(value_type, const basic_string&); friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+<>(const basic_string&, const value_type*); friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+<>(const basic_string&, value_type); }; // These declarations must appear before any functions are implicitly used // so that they have the correct visibility specifier. #define _LIBCPP_DECLARE(...) extern template __VA_ARGS__; #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char) # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t) # endif #else _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char) # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t) # endif #endif #undef _LIBCPP_DECLARE #if _LIBCPP_STD_VER >= 17 template<class _InputIterator, class _CharT = __iter_value_type<_InputIterator>, class _Allocator = allocator<_CharT>, class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Allocator>::value> > basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator()) -> basic_string<_CharT, char_traits<_CharT>, _Allocator>; template<class _CharT, class _Traits, class _Allocator = allocator<_CharT>, class = enable_if_t<__is_allocator<_Allocator>::value> > explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator()) -> basic_string<_CharT, _Traits, _Allocator>; template<class _CharT, class _Traits, class _Allocator = allocator<_CharT>, class = enable_if_t<__is_allocator<_Allocator>::value>, class _Sz = typename allocator_traits<_Allocator>::size_type > basic_string(basic_string_view<_CharT, _Traits>, _Sz, _Sz, const _Allocator& = _Allocator()) -> basic_string<_CharT, _Traits, _Allocator>; #endif #if _LIBCPP_STD_VER >= 23 template <ranges::input_range _Range, class _Allocator = allocator<ranges::range_value_t<_Range>>, class = enable_if_t<__is_allocator<_Allocator>::value> > basic_string(from_range_t, _Range&&, _Allocator = _Allocator()) -> basic_string<ranges::range_value_t<_Range>, char_traits<ranges::range_value_t<_Range>>, _Allocator>; #endif template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz, size_type __reserve) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); if (__reserve > max_size()) __throw_length_error(); pointer __p; if (__fits_in_sso(__reserve)) { __set_short_size(__sz); __p = __get_short_pointer(); } else { auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__reserve) + 1); __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); __set_long_pointer(__p); __set_long_cap(__allocation.count); __set_long_size(__sz); } traits_type::copy(std::__to_address(__p), __s, __sz); traits_type::assign(__p[__sz], value_type()); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); if (__sz > max_size()) __throw_length_error(); pointer __p; if (__fits_in_sso(__sz)) { __set_short_size(__sz); __p = __get_short_pointer(); } else { auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1); __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); __set_long_pointer(__p); __set_long_cap(__allocation.count); __set_long_size(__sz); } traits_type::copy(std::__to_address(__p), __s, __sz); traits_type::assign(__p[__sz], value_type()); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external( const value_type* __s, size_type __sz) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); pointer __p; if (__fits_in_sso(__sz)) { __p = __get_short_pointer(); __set_short_size(__sz); } else { if (__sz > max_size()) __throw_length_error(); auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1); __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); __set_long_pointer(__p); __set_long_cap(__allocation.count); __set_long_size(__sz); } traits_type::copy(std::__to_address(__p), __s, __sz + 1); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); if (__n > max_size()) __throw_length_error(); pointer __p; if (__fits_in_sso(__n)) { __set_short_size(__n); __p = __get_short_pointer(); } else { auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__n) + 1); __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); __set_long_pointer(__p); __set_long_cap(__allocation.count); __set_long_size(__n); } traits_type::assign(std::__to_address(__p), __n, __c); traits_type::assign(__p[__n], value_type()); } template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last) { __init_with_sentinel(std::move(__first), std::move(__last)); } template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator __first, _Sentinel __last) { __r_.first() = __rep(); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __first != __last; ++__first) push_back(*__first); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; } #endif // _LIBCPP_HAS_NO_EXCEPTIONS } template <class _CharT, class _Traits, class _Allocator> template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _ForwardIterator __last) { size_type __sz = static_cast<size_type>(std::distance(__first, __last)); __init_with_size(__first, __last, __sz); } template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init_with_size( _InputIterator __first, _Sentinel __last, size_type __sz) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); if (__sz > max_size()) __throw_length_error(); pointer __p; if (__fits_in_sso(__sz)) { __set_short_size(__sz); __p = __get_short_pointer(); } else { auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1); __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); __set_long_pointer(__p); __set_long_cap(__allocation.count); __set_long_size(__sz); } #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __first != __last; ++__first, (void) ++__p) traits_type::assign(*__p, *__first); traits_type::assign(*__p, value_type()); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; } #endif // _LIBCPP_HAS_NO_EXCEPTIONS } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace (size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add, const value_type* __p_new_stuff) { size_type __ms = max_size(); if (__delta_cap > __ms - __old_cap - 1) __throw_length_error(); pointer __old_p = __get_pointer(); size_type __cap = __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1; auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); if (__n_copy != 0) traits_type::copy(std::__to_address(__p), std::__to_address(__old_p), __n_copy); if (__n_add != 0) traits_type::copy(std::__to_address(__p) + __n_copy, __p_new_stuff, __n_add); size_type __sec_cp_sz = __old_sz - __n_del - __n_copy; if (__sec_cp_sz != 0) traits_type::copy(std::__to_address(__p) + __n_copy + __n_add, std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz); if (__old_cap+1 != __min_cap) __alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1); __set_long_pointer(__p); __set_long_cap(__allocation.count); __old_sz = __n_copy + __n_add + __sec_cp_sz; __set_long_size(__old_sz); traits_type::assign(__p[__old_sz], value_type()); } // __grow_by is deprecated because it does not set the size. It may not update the size when the size is changed, and it // may also not set the size at all when the string was short initially. This leads to unpredictable size value. It is // not removed or changed to avoid breaking the ABI. template <class _CharT, class _Traits, class _Allocator> void _LIBCPP_CONSTEXPR_SINCE_CXX20 #if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1 _LIBCPP_HIDE_FROM_ABI #endif _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add) { size_type __ms = max_size(); if (__delta_cap > __ms - __old_cap) __throw_length_error(); pointer __old_p = __get_pointer(); size_type __cap = __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1; auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); if (__n_copy != 0) traits_type::copy(std::__to_address(__p), std::__to_address(__old_p), __n_copy); size_type __sec_cp_sz = __old_sz - __n_del - __n_copy; if (__sec_cp_sz != 0) traits_type::copy(std::__to_address(__p) + __n_copy + __n_add, std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz); if (__old_cap + 1 != __min_cap) __alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1); __set_long_pointer(__p); __set_long_cap(__allocation.count); } template <class _CharT, class _Traits, class _Allocator> void _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace( size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add) { _LIBCPP_SUPPRESS_DEPRECATED_PUSH __grow_by(__old_cap, __delta_cap, __old_sz, __n_copy, __n_del, __n_add); _LIBCPP_SUPPRESS_DEPRECATED_POP __set_long_size(__old_sz - __n_del + __n_add); } // assign template <class _CharT, class _Traits, class _Allocator> template <bool __is_short> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias( const value_type* __s, size_type __n) { size_type __cap = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap(); if (__n < __cap) { pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer(); __is_short ? __set_short_size(__n) : __set_long_size(__n); traits_type::copy(std::__to_address(__p), __s, __n); traits_type::assign(__p[__n], value_type()); } else { size_type __sz = __is_short ? __get_short_size() : __get_long_size(); __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s); } return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::__assign_external( const value_type* __s, size_type __n) { size_type __cap = capacity(); if (__cap >= __n) { value_type* __p = std::__to_address(__get_pointer()); traits_type::move(__p, __s, __n); return __null_terminate_at(__p, __n); } else { size_type __sz = size(); __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s); return *this; } } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n) { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::assign received nullptr"); return (__builtin_constant_p(__n) && __fits_in_sso(__n)) ? __assign_short(__s, __n) : __assign_external(__s, __n); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c) { size_type __cap = capacity(); if (__cap < __n) { size_type __sz = size(); __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); } value_type* __p = std::__to_address(__get_pointer()); traits_type::assign(__p, __n, __c); return __null_terminate_at(__p, __n); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { pointer __p; if (__is_long()) { __p = __get_long_pointer(); __set_long_size(1); } else { __p = __get_short_pointer(); __set_short_size(1); } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) { if (this != std::addressof(__str)) { __copy_assign_alloc(__str); if (!__is_long()) { if (!__str.__is_long()) { __r_.first() = __str.__r_.first(); } else { return __assign_no_alias<true>(__str.data(), __str.size()); } } else { return __assign_no_alias<false>(__str.data(), __str.size()); } } return *this; } #ifndef _LIBCPP_CXX03_LANG template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value) { if (__alloc() != __str.__alloc()) assign(__str); else __move_assign(__str, true_type()); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type) #if _LIBCPP_STD_VER >= 17 _NOEXCEPT #else _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) #endif { if (__is_long()) { __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); #if _LIBCPP_STD_VER <= 14 if (!is_nothrow_move_assignable<allocator_type>::value) { __set_short_size(0); traits_type::assign(__get_short_pointer()[0], value_type()); } #endif } __move_assign_alloc(__str); __r_.first() = __str.__r_.first(); __str.__set_short_size(0); traits_type::assign(__str.__get_short_pointer()[0], value_type()); } #endif template <class _CharT, class _Traits, class _Allocator> template<class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { __assign_with_sentinel(__first, __last); return *this; } template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__assign_with_sentinel(_InputIterator __first, _Sentinel __last) { const basic_string __temp(__init_with_sentinel_tag(), std::move(__first), std::move(__last), __alloc()); assign(__temp.data(), __temp.size()); } template <class _CharT, class _Traits, class _Allocator> template<class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) { if (__string_is_trivial_iterator<_ForwardIterator>::value) { size_type __n = static_cast<size_type>(std::distance(__first, __last)); __assign_trivial(__first, __last, __n); } else { __assign_with_sentinel(__first, __last); } return *this; } template <class _CharT, class _Traits, class _Allocator> template <class _Iterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _Sentinel __last, size_type __n) { _LIBCPP_ASSERT_INTERNAL( __string_is_trivial_iterator<_Iterator>::value, "The iterator type given to `__assign_trivial` must be trivial"); size_type __cap = capacity(); if (__cap < __n) { // Unlike `append` functions, if the input range points into the string itself, there is no case that the input // range could get invalidated by reallocation: // 1. If the input range is a subset of the string itself, its size cannot exceed the capacity of the string, // thus no reallocation would happen. // 2. In the exotic case where the input range is the byte representation of the string itself, the string // object itself stays valid even if reallocation happens. size_type __sz = size(); __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); } pointer __p = __get_pointer(); for (; __first != __last; ++__p, (void) ++__first) traits_type::assign(*__p, *__first); traits_type::assign(*__p, value_type()); __set_size(__n); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, size_type __pos, size_type __n) { size_type __sz = __str.size(); if (__pos > __sz) __throw_out_of_range(); return assign(__str.data() + __pos, std::min(__n, __sz - __pos)); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp& __t, size_type __pos, size_type __n) { __self_view __sv = __t; size_type __sz = __sv.size(); if (__pos > __sz) __throw_out_of_range(); return assign(__sv.data() + __pos, std::min(__n, __sz - __pos)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) { return __assign_external(__s, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::assign received nullptr"); return __builtin_constant_p(*__s) ? (__fits_in_sso(traits_type::length(__s)) ? __assign_short(__s, traits_type::length(__s)) : __assign_external(__s, traits_type::length(__s))) : __assign_external(__s); } // append template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_type __n) { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::append received nullptr"); size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz >= __n) { if (__n) { value_type* __p = std::__to_address(__get_pointer()); traits_type::copy(__p + __sz, __s, __n); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } } else __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __sz, 0, __n, __s); return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c) { if (__n) { size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz < __n) __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); pointer __p = __get_pointer(); traits_type::assign(std::__to_address(__p) + __sz, __n, __c); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 inline void basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n) { if (__n) { size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz < __n) __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); pointer __p = __get_pointer(); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c) { bool __is_short = !__is_long(); size_type __cap; size_type __sz; if (__is_short) { __cap = __min_cap - 1; __sz = __get_short_size(); } else { __cap = __get_long_cap() - 1; __sz = __get_long_size(); } if (__sz == __cap) { __grow_by_without_replace(__cap, 1, __sz, __sz, 0); __is_short = false; // the string is always long after __grow_by } pointer __p = __get_pointer(); if (__is_short) { __p = __get_short_pointer() + __sz; __set_short_size(__sz+1); } else { __p = __get_long_pointer() + __sz; __set_long_size(__sz+1); } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); } template <class _CharT, class _Traits, class _Allocator> template<class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append( _ForwardIterator __first, _ForwardIterator __last) { size_type __sz = size(); size_type __cap = capacity(); size_type __n = static_cast<size_type>(std::distance(__first, __last)); if (__n) { if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first)) { if (__cap - __sz < __n) __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); pointer __p = __get_pointer() + __sz; for (; __first != __last; ++__p, (void) ++__first) traits_type::assign(*__p, *__first); traits_type::assign(*__p, value_type()); __set_size(__sz + __n); } else { const basic_string __temp(__first, __last, __alloc()); append(__temp.data(), __temp.size()); } } return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, size_type __pos, size_type __n) { size_type __sz = __str.size(); if (__pos > __sz) __throw_out_of_range(); return append(__str.data() + __pos, std::min(__n, __sz - __pos)); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const _Tp& __t, size_type __pos, size_type __n) { __self_view __sv = __t; size_type __sz = __sv.size(); if (__pos > __sz) __throw_out_of_range(); return append(__sv.data() + __pos, std::min(__n, __sz - __pos)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::append received nullptr"); return append(__s, traits_type::length(__s)); } // insert template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s, size_type __n) { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::insert received nullptr"); size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); size_type __cap = capacity(); if (__cap - __sz >= __n) { if (__n) { value_type* __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) { if (std::__is_pointer_in_range(__p + __pos, __p + __sz, __s)) __s += __n; traits_type::move(__p + __pos + __n, __p + __pos, __n_move); } traits_type::move(__p + __pos, __s, __n); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } } else __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n, __s); return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n, value_type __c) { size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); if (__n) { size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) traits_type::move(__p + __pos + __n, __p + __pos, __n_move); } else { __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n); __p = std::__to_address(__get_long_pointer()); } traits_type::assign(__p + __pos, __n, __c); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } return *this; } template <class _CharT, class _Traits, class _Allocator> template<class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) { const basic_string __temp(__first, __last, __alloc()); return insert(__pos, __temp.data(), __temp.data() + __temp.size()); } template <class _CharT, class _Traits, class _Allocator> template<class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) { auto __n = static_cast<size_type>(std::distance(__first, __last)); return __insert_with_size(__pos, __first, __last, __n); } template <class _CharT, class _Traits, class _Allocator> template<class _Iterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::__insert_with_size( const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n) { size_type __ip = static_cast<size_type>(__pos - begin()); if (__n == 0) return begin() + __ip; if (__string_is_trivial_iterator<_Iterator>::value && !__addr_in_range(*__first)) { return __insert_from_safe_copy(__n, __ip, __first, __last); } else { const basic_string __temp(__init_with_sentinel_tag(), __first, __last, __alloc()); return __insert_from_safe_copy(__n, __ip, __temp.begin(), __temp.end()); } } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n) { size_type __str_sz = __str.size(); if (__pos2 > __str_sz) __throw_out_of_range(); return insert(__pos1, __str.data() + __pos2, std::min(__n, __str_sz - __pos2)); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n) { __self_view __sv = __t; size_type __str_sz = __sv.size(); if (__pos2 > __str_sz) __throw_out_of_range(); return insert(__pos1, __sv.data() + __pos2, std::min(__n, __str_sz - __pos2)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::insert received nullptr"); return insert(__pos, __s, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_type __c) { size_type __ip = static_cast<size_type>(__pos - begin()); size_type __sz = size(); size_type __cap = capacity(); value_type* __p; if (__cap == __sz) { __grow_by_without_replace(__cap, 1, __sz, __ip, 0, 1); __p = std::__to_address(__get_long_pointer()); } else { __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) traits_type::move(__p + __ip + 1, __p + __ip, __n_move); } traits_type::assign(__p[__ip], __c); traits_type::assign(__p[++__sz], value_type()); __set_size(__sz); return begin() + static_cast<difference_type>(__ip); } // replace template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { _LIBCPP_ASSERT_NON_NULL(__n2 == 0 || __s != nullptr, "string::replace received nullptr"); size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); __n1 = std::min(__n1, __sz - __pos); size_type __cap = capacity(); if (__cap - __sz + __n1 >= __n2) { value_type* __p = std::__to_address(__get_pointer()); if (__n1 != __n2) { size_type __n_move = __sz - __pos - __n1; if (__n_move != 0) { if (__n1 > __n2) { traits_type::move(__p + __pos, __s, __n2); traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); return __null_terminate_at(__p, __sz + (__n2 - __n1)); } if (std::__is_pointer_in_range(__p + __pos + 1, __p + __sz, __s)) { if (__p + __pos + __n1 <= __s) __s += __n2 - __n1; else // __p + __pos < __s < __p + __pos + __n1 { traits_type::move(__p + __pos, __s, __n1); __pos += __n1; __s += __n2; __n2 -= __n1; __n1 = 0; } } traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); } } traits_type::move(__p + __pos, __s, __n2); return __null_terminate_at(__p, __sz + (__n2 - __n1)); } else __grow_by_and_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2, __s); return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, size_type __n2, value_type __c) { size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); __n1 = std::min(__n1, __sz - __pos); size_type __cap = capacity(); value_type* __p; if (__cap - __sz + __n1 >= __n2) { __p = std::__to_address(__get_pointer()); if (__n1 != __n2) { size_type __n_move = __sz - __pos - __n1; if (__n_move != 0) traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); } } else { __grow_by_without_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2); __p = std::__to_address(__get_long_pointer()); } traits_type::assign(__p + __pos, __n2, __c); return __null_terminate_at(__p, __sz - (__n1 - __n2)); } template <class _CharT, class _Traits, class _Allocator> template<class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2) { const basic_string __temp(__j1, __j2, __alloc()); return replace(__i1, __i2, __temp); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2) { size_type __str_sz = __str.size(); if (__pos2 > __str_sz) __throw_out_of_range(); return replace(__pos1, __n1, __str.data() + __pos2, std::min(__n2, __str_sz - __pos2)); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace( size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) { __self_view __sv = __t; size_type __str_sz = __sv.size(); if (__pos2 > __str_sz) __throw_out_of_range(); return replace(__pos1, __n1, __sv.data() + __pos2, std::min(__n2, __str_sz - __pos2)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::replace received nullptr"); return replace(__pos, __n1, __s, traits_type::length(__s)); } // erase // 'externally instantiated' erase() implementation, called when __n != npos. // Does not check __pos against size() template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void basic_string<_CharT, _Traits, _Allocator>::__erase_external_with_move( size_type __pos, size_type __n) { if (__n) { size_type __sz = size(); value_type* __p = std::__to_address(__get_pointer()); __n = std::min(__n, __sz - __pos); size_type __n_move = __sz - __pos - __n; if (__n_move != 0) traits_type::move(__p + __pos, __p + __pos + __n, __n_move); __null_terminate_at(__p, __sz - __n); } } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, size_type __n) { if (__pos > size()) __throw_out_of_range(); if (__n == npos) { __erase_to_end(__pos); } else { __erase_external_with_move(__pos, __n); } return *this; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __pos != end(), "string::erase(iterator) called with a non-dereferenceable iterator"); iterator __b = begin(); size_type __r = static_cast<size_type>(__pos - __b); erase(__r, 1); return __b + static_cast<difference_type>(__r); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "string::erase(first, last) called with invalid range"); iterator __b = begin(); size_type __r = static_cast<size_type>(__first - __b); erase(__r, static_cast<size_type>(__last - __first)); return __b + static_cast<difference_type>(__r); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pop_back() { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty"); __erase_to_end(size() - 1); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT { if (__is_long()) { traits_type::assign(*__get_long_pointer(), value_type()); __set_long_size(0); } else { traits_type::assign(*__get_short_pointer(), value_type()); __set_short_size(0); } } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::resize(size_type __n, value_type __c) { size_type __sz = size(); if (__n > __sz) append(__n - __sz, __c); else __erase_to_end(__n); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 inline void basic_string<_CharT, _Traits, _Allocator>::__resize_default_init(size_type __n) { size_type __sz = size(); if (__n > __sz) { __append_default_init(__n - __sz); } else __erase_to_end(__n); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::reserve(size_type __requested_capacity) { if (__requested_capacity > max_size()) __throw_length_error(); // Make sure reserve(n) never shrinks. This is technically only required in C++20 // and later (since P0966R1), however we provide consistent behavior in all Standard // modes because this function is instantiated in the shared library. if (__requested_capacity <= capacity()) return; size_type __target_capacity = std::max(__requested_capacity, size()); __target_capacity = __recommend(__target_capacity); if (__target_capacity == capacity()) return; __shrink_or_extend(__target_capacity); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::shrink_to_fit() _NOEXCEPT { size_type __target_capacity = __recommend(size()); if (__target_capacity == capacity()) return; __shrink_or_extend(__target_capacity); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity) { size_type __cap = capacity(); size_type __sz = size(); pointer __new_data, __p; bool __was_long, __now_long; if (__fits_in_sso(__target_capacity)) { __was_long = true; __now_long = false; __new_data = __get_short_pointer(); __p = __get_long_pointer(); } else { if (__target_capacity > __cap) { auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1); __new_data = __allocation.ptr; __target_capacity = __allocation.count - 1; } else { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif // _LIBCPP_HAS_NO_EXCEPTIONS auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1); __new_data = __allocation.ptr; __target_capacity = __allocation.count - 1; #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { return; } #else // _LIBCPP_HAS_NO_EXCEPTIONS if (__new_data == nullptr) return; #endif // _LIBCPP_HAS_NO_EXCEPTIONS } __begin_lifetime(__new_data, __target_capacity + 1); __now_long = true; __was_long = __is_long(); __p = __get_pointer(); } traits_type::copy(std::__to_address(__new_data), std::__to_address(__p), size()+1); if (__was_long) __alloc_traits::deallocate(__alloc(), __p, __cap+1); if (__now_long) { __set_long_cap(__target_capacity+1); __set_long_size(__sz); __set_long_pointer(__new_data); } else __set_short_size(__sz); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const { if (__n >= size()) __throw_out_of_range(); return (*this)[__n]; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) { if (__n >= size()) __throw_out_of_range(); return (*this)[__n]; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::copy(value_type* __s, size_type __n, size_type __pos) const { size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); size_type __rlen = std::min(__n, __sz - __pos); traits_type::copy(__s, data() + __pos, __rlen); return __rlen; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value) #endif { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value || __alloc() == __str.__alloc(), "swapping non-equal allocators"); std::swap(__r_.first(), __str.__r_.first()); std::__swap_allocator(__alloc(), __str.__alloc()); } // find template <class _Traits> struct _LIBCPP_HIDDEN __traits_eq { typedef typename _Traits::char_type char_type; _LIBCPP_HIDE_FROM_ABI bool operator()(const char_type& __x, const char_type& __y) _NOEXCEPT {return _Traits::eq(__x, __y);} }; template<class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find(): received nullptr"); return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } template<class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const _Tp &__t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find(): received nullptr"); return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } template<class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(value_type __c, size_type __pos) const _NOEXCEPT { return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } // rfind template<class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::rfind(): received nullptr"); return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } template<class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::rfind(): received nullptr"); return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } template<class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(value_type __c, size_type __pos) const _NOEXCEPT { return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } // find_first_of template<class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr"); return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } template<class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_first_of(): received nullptr"); return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(value_type __c, size_type __pos) const _NOEXCEPT { return find(__c, __pos); } // find_last_of template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr"); return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } template<class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_last_of(): received nullptr"); return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(value_type __c, size_type __pos) const _NOEXCEPT { return rfind(__c, __pos); } // find_first_not_of template<class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } template<class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c, size_type __pos) const _NOEXCEPT { return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } // find_last_not_of template<class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __str.data(), __pos, __str.size()); } template<class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __sv.data(), __pos, __sv.size()); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c, size_type __pos) const _NOEXCEPT { return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __c, __pos); } // compare template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const _NOEXCEPT { __self_view __sv = __t; size_t __lhs_sz = size(); size_t __rhs_sz = __sv.size(); int __result = traits_type::compare(data(), __sv.data(), std::min(__lhs_sz, __rhs_sz)); if (__result != 0) return __result; if (__lhs_sz < __rhs_sz) return -1; if (__lhs_sz > __rhs_sz) return 1; return 0; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const basic_string& __str) const _NOEXCEPT { return compare(__self_view(__str)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const { _LIBCPP_ASSERT_NON_NULL(__n2 == 0 || __s != nullptr, "string::compare(): received nullptr"); size_type __sz = size(); if (__pos1 > __sz || __n2 == npos) __throw_out_of_range(); size_type __rlen = std::min(__n1, __sz - __pos1); int __r = traits_type::compare(data() + __pos1, __s, std::min(__rlen, __n2)); if (__r == 0) { if (__rlen < __n2) __r = -1; else if (__rlen > __n2) __r = 1; } return __r; } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const _Tp& __t) const { __self_view __sv = __t; return compare(__pos1, __n1, __sv.data(), __sv.size()); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const basic_string& __str) const { return compare(__pos1, __n1, __str.data(), __str.size()); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare( size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) const { __self_view __sv = __t; return __self_view(*this).substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2) const { return compare(__pos1, __n1, __self_view(__str), __pos2, __n2); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const value_type* __s) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::compare(): received nullptr"); return compare(0, npos, __s, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const value_type* __s) const { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::compare(): received nullptr"); return compare(__pos1, __n1, __s, traits_type::length(__s)); } // __invariants template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 bool basic_string<_CharT, _Traits, _Allocator>::__invariants() const { if (size() > capacity()) return false; if (capacity() < __min_cap - 1) return false; if (data() == nullptr) return false; if (!_Traits::eq(data()[size()], value_type())) return false; return true; } // __clear_and_shrink template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT { clear(); if(__is_long()) { __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1); __r_.first() = __rep(); } } // operator== template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { #if _LIBCPP_STD_VER >= 20 return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs); #else size_t __lhs_sz = __lhs.size(); return __lhs_sz == __rhs.size() && _Traits::compare(__lhs.data(), __rhs.data(), __lhs_sz) == 0; #endif } template<class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool operator==(const basic_string<char, char_traits<char>, _Allocator>& __lhs, const basic_string<char, char_traits<char>, _Allocator>& __rhs) _NOEXCEPT { size_t __lhs_sz = __lhs.size(); if (__lhs_sz != __rhs.size()) return false; const char* __lp = __lhs.data(); const char* __rp = __rhs.data(); if (__lhs.__is_long()) return char_traits<char>::compare(__lp, __rp, __lhs_sz) == 0; for (; __lhs_sz != 0; --__lhs_sz, ++__lp, ++__rp) if (*__lp != *__rp) return false; return true; } #if _LIBCPP_STD_VER <= 17 template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator==(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { typedef basic_string<_CharT, _Traits, _Allocator> _String; _LIBCPP_ASSERT_NON_NULL(__lhs != nullptr, "operator==(char*, basic_string): received nullptr"); size_t __lhs_len = _Traits::length(__lhs); if (__lhs_len != __rhs.size()) return false; return __rhs.compare(0, _String::npos, __lhs, __lhs_len) == 0; } #endif // _LIBCPP_STD_VER <= 17 template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { #if _LIBCPP_STD_VER >= 20 return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs); #else typedef basic_string<_CharT, _Traits, _Allocator> _String; _LIBCPP_ASSERT_NON_NULL(__rhs != nullptr, "operator==(basic_string, char*): received nullptr"); size_t __rhs_len = _Traits::length(__rhs); if (__rhs_len != __lhs.size()) return false; return __lhs.compare(0, _String::npos, __rhs, __rhs_len) == 0; #endif } #if _LIBCPP_STD_VER >= 20 template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>( const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) noexcept { return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs); } #else // _LIBCPP_STD_VER >= 20 template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs == __rhs); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs == __rhs); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return !(__lhs == __rhs); } // operator< template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __lhs.compare(__rhs) < 0; } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return __lhs.compare(__rhs) < 0; } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator< (const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __rhs.compare(__lhs) > 0; } // operator> template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __rhs < __lhs; } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return __rhs < __lhs; } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator> (const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __rhs < __lhs; } // operator<= template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__rhs < __lhs); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return !(__rhs < __lhs); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__rhs < __lhs); } // operator>= template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs < __rhs); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return !(__lhs < __rhs); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs < __rhs); } #endif // _LIBCPP_STD_VER >= 20 // operator + template<class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { using _String = basic_string<_CharT, _Traits, _Allocator>; auto __lhs_sz = __lhs.size(); auto __rhs_sz = __rhs.size(); _String __r(__uninitialized_size_tag(), __lhs_sz + __rhs_sz, _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator())); auto __ptr = std::__to_address(__r.__get_pointer()); _Traits::copy(__ptr, __lhs.data(), __lhs_sz); _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz); _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT()); return __r; } template<class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const _CharT* __lhs , const basic_string<_CharT,_Traits,_Allocator>& __rhs) { using _String = basic_string<_CharT, _Traits, _Allocator>; auto __lhs_sz = _Traits::length(__lhs); auto __rhs_sz = __rhs.size(); _String __r(__uninitialized_size_tag(), __lhs_sz + __rhs_sz, _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator())); auto __ptr = std::__to_address(__r.__get_pointer()); _Traits::copy(__ptr, __lhs, __lhs_sz); _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz); _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT()); return __r; } template<class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Allocator>& __rhs) { using _String = basic_string<_CharT, _Traits, _Allocator>; typename _String::size_type __rhs_sz = __rhs.size(); _String __r(__uninitialized_size_tag(), __rhs_sz + 1, _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator())); auto __ptr = std::__to_address(__r.__get_pointer()); _Traits::assign(__ptr, 1, __lhs); _Traits::copy(__ptr + 1, __rhs.data(), __rhs_sz); _Traits::assign(__ptr + 1 + __rhs_sz, 1, _CharT()); return __r; } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { using _String = basic_string<_CharT, _Traits, _Allocator>; typename _String::size_type __lhs_sz = __lhs.size(); typename _String::size_type __rhs_sz = _Traits::length(__rhs); _String __r(__uninitialized_size_tag(), __lhs_sz + __rhs_sz, _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator())); auto __ptr = std::__to_address(__r.__get_pointer()); _Traits::copy(__ptr, __lhs.data(), __lhs_sz); _Traits::copy(__ptr + __lhs_sz, __rhs, __rhs_sz); _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT()); return __r; } template<class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, _CharT __rhs) { using _String = basic_string<_CharT, _Traits, _Allocator>; typename _String::size_type __lhs_sz = __lhs.size(); _String __r(__uninitialized_size_tag(), __lhs_sz + 1, _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator())); auto __ptr = std::__to_address(__r.__get_pointer()); _Traits::copy(__ptr, __lhs.data(), __lhs_sz); _Traits::assign(__ptr + __lhs_sz, 1, __rhs); _Traits::assign(__ptr + 1 + __lhs_sz, 1, _CharT()); return __r; } #ifndef _LIBCPP_CXX03_LANG template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { return std::move(__lhs.append(__rhs)); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { return std::move(__rhs.insert(0, __lhs)); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { return std::move(__lhs.append(__rhs)); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const _CharT* __lhs , basic_string<_CharT,_Traits,_Allocator>&& __rhs) { return std::move(__rhs.insert(0, __lhs)); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(_CharT __lhs, basic_string<_CharT,_Traits,_Allocator>&& __rhs) { __rhs.insert(__rhs.begin(), __lhs); return std::move(__rhs); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const _CharT* __rhs) { return std::move(__lhs.append(__rhs)); } template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, _CharT __rhs) { __lhs.push_back(__rhs); return std::move(__lhs); } #endif // _LIBCPP_CXX03_LANG // swap template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT_(_NOEXCEPT_(__lhs.swap(__rhs))) { __lhs.swap(__rhs); } _LIBCPP_EXPORTED_FROM_ABI int stoi (const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI long stol (const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI unsigned long stoul (const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI long long stoll (const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI unsigned long long stoull(const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI float stof (const string& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI double stod (const string& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI long double stold(const string& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI string to_string(int __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(long __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned long __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(long long __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned long long __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(float __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(double __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(long double __val); #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_EXPORTED_FROM_ABI int stoi (const wstring& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI long stol (const wstring& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI unsigned long stoul (const wstring& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI long long stoll (const wstring& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI unsigned long long stoull(const wstring& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI float stof (const wstring& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI double stod (const wstring& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI long double stold(const wstring& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(int __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned long __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long long __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned long long __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(float __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(double __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long double __val); #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS template<class _CharT, class _Traits, class _Allocator> _LIBCPP_TEMPLATE_DATA_VIS const typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::npos; template <class _CharT, class _Allocator> struct __string_hash : public __unary_function<basic_string<_CharT, char_traits<_CharT>, _Allocator>, size_t> { _LIBCPP_HIDE_FROM_ABI size_t operator()(const basic_string<_CharT, char_traits<_CharT>, _Allocator>& __val) const _NOEXCEPT { return std::__do_string_hash(__val.data(), __val.data() + __val.size()); } }; template <class _Allocator> struct hash<basic_string<char, char_traits<char>, _Allocator> > : __string_hash<char, _Allocator> {}; #ifndef _LIBCPP_HAS_NO_CHAR8_T template <class _Allocator> struct hash<basic_string<char8_t, char_traits<char8_t>, _Allocator> > : __string_hash<char8_t, _Allocator> {}; #endif template <class _Allocator> struct hash<basic_string<char16_t, char_traits<char16_t>, _Allocator> > : __string_hash<char16_t, _Allocator> {}; template <class _Allocator> struct hash<basic_string<char32_t, char_traits<char32_t>, _Allocator> > : __string_hash<char32_t, _Allocator> {}; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class _Allocator> struct hash<basic_string<wchar_t, char_traits<wchar_t>, _Allocator> > : __string_hash<wchar_t, _Allocator> {}; #endif template<class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const basic_string<_CharT, _Traits, _Allocator>& __str); template<class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& operator>>(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str); template<class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm); template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str); template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm); template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str); #if _LIBCPP_STD_VER >= 20 template <class _CharT, class _Traits, class _Allocator, class _Up> inline _LIBCPP_HIDE_FROM_ABI typename basic_string<_CharT, _Traits, _Allocator>::size_type erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) { auto __old_size = __str.size(); __str.erase(std::remove(__str.begin(), __str.end(), __v), __str.end()); return __old_size - __str.size(); } template <class _CharT, class _Traits, class _Allocator, class _Predicate> inline _LIBCPP_HIDE_FROM_ABI typename basic_string<_CharT, _Traits, _Allocator>::size_type erase_if(basic_string<_CharT, _Traits, _Allocator>& __str, _Predicate __pred) { auto __old_size = __str.size(); __str.erase(std::remove_if(__str.begin(), __str.end(), __pred), __str.end()); return __old_size - __str.size(); } #endif #if _LIBCPP_STD_VER >= 14 // Literal suffixes for basic_string [basic.string.literals] inline namespace literals { inline namespace string_literals { inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char> operator""s( const char *__str, size_t __len ) { return basic_string<char> (__str, __len); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<wchar_t> operator""s( const wchar_t *__str, size_t __len ) { return basic_string<wchar_t> (__str, __len); } #endif #ifndef _LIBCPP_HAS_NO_CHAR8_T inline _LIBCPP_HIDE_FROM_ABI constexpr basic_string<char8_t> operator""s(const char8_t *__str, size_t __len) { return basic_string<char8_t> (__str, __len); } #endif inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char16_t> operator""s( const char16_t *__str, size_t __len ) { return basic_string<char16_t> (__str, __len); } inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char32_t> operator""s( const char32_t *__str, size_t __len ) { return basic_string<char32_t> (__str, __len); } } // namespace string_literals } // namespace literals #if _LIBCPP_STD_VER >= 20 template <> inline constexpr bool __format::__enable_insertable<std::basic_string<char>> = true; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> inline constexpr bool __format::__enable_insertable<std::basic_string<wchar_t>> = true; #endif #endif #endif _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <algorithm> # include <concepts> # include <cstdlib> # include <iterator> # include <new> # include <type_traits> # include <typeinfo> # include <utility> #endif #endif // _LIBCPP_STRING #endif // _LIBCPP_OLD_STRING #ifdef _LIBCPP_NEW_STRING // -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_STRING #define _LIBCPP_STRING // clang-format off /* string synopsis #include <compare> #include <initializer_list> namespace std { template <class stateT> class fpos { private: stateT st; public: fpos(streamoff = streamoff()); operator streamoff() const; stateT state() const; void state(stateT); fpos& operator+=(streamoff); fpos operator+ (streamoff) const; fpos& operator-=(streamoff); fpos operator- (streamoff) const; }; template <class stateT> streamoff operator-(const fpos<stateT>& x, const fpos<stateT>& y); template <class stateT> bool operator==(const fpos<stateT>& x, const fpos<stateT>& y); template <class stateT> bool operator!=(const fpos<stateT>& x, const fpos<stateT>& y); template <class charT> struct char_traits { using char_type = charT; using int_type = ...; using off_type = streamoff; using pos_type = streampos; using state_type = mbstate_t; using comparison_category = strong_ordering; // Since C++20 only for the specializations // char, wchar_t, char8_t, char16_t, and char32_t. static void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static int compare(const char_type* s1, const char_type* s2, size_t n); static size_t length(const char_type* s); static const char_type* find(const char_type* s, size_t n, const char_type& a); static char_type* move(char_type* s1, const char_type* s2, size_t n); static char_type* copy(char_type* s1, const char_type* s2, size_t n); static char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; }; template <> struct char_traits<char>; template <> struct char_traits<wchar_t>; template <> struct char_traits<char8_t>; // C++20 template <> struct char_traits<char16_t>; template <> struct char_traits<char32_t>; template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > class basic_string { public: // types: typedef traits traits_type; typedef typename traits_type::char_type value_type; typedef Allocator allocator_type; typedef typename allocator_type::size_type size_type; typedef typename allocator_type::difference_type difference_type; typedef typename allocator_type::reference reference; typedef typename allocator_type::const_reference const_reference; typedef typename allocator_type::pointer pointer; typedef typename allocator_type::const_pointer const_pointer; typedef implementation-defined iterator; typedef implementation-defined const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; static const size_type npos = -1; basic_string() noexcept(is_nothrow_default_constructible<allocator_type>::value); // constexpr since C++20 explicit basic_string(const allocator_type& a); // constexpr since C++20 basic_string(const basic_string& str); // constexpr since C++20 basic_string(basic_string&& str) noexcept(is_nothrow_move_constructible<allocator_type>::value); // constexpr since C++20 basic_string(const basic_string& str, size_type pos, const allocator_type& a = allocator_type()); // constexpr since C++20 basic_string(const basic_string& str, size_type pos, size_type n, const Allocator& a = Allocator()); // constexpr since C++20 constexpr basic_string( basic_string&& str, size_type pos, const Allocator& a = Allocator()); // since C++23 constexpr basic_string( basic_string&& str, size_type pos, size_type n, const Allocator& a = Allocator()); // since C++23 template<class T> basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); // C++17, constexpr since C++20 template <class T> explicit basic_string(const T& t, const Allocator& a = Allocator()); // C++17, constexpr since C++20 basic_string(const value_type* s, const allocator_type& a = allocator_type()); // constexpr since C++20 basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); // constexpr since C++20 basic_string(nullptr_t) = delete; // C++23 basic_string(size_type n, value_type c, const allocator_type& a = allocator_type()); // constexpr since C++20 template<class InputIterator> basic_string(InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()); // constexpr since C++20 template<container-compatible-range<charT> R> constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); // since C++23 basic_string(initializer_list<value_type>, const Allocator& = Allocator()); // constexpr since C++20 basic_string(const basic_string&, const Allocator&); // constexpr since C++20 basic_string(basic_string&&, const Allocator&); // constexpr since C++20 ~basic_string(); // constexpr since C++20 operator basic_string_view<charT, traits>() const noexcept; // constexpr since C++20 basic_string& operator=(const basic_string& str); // constexpr since C++20 template <class T> basic_string& operator=(const T& t); // C++17, constexpr since C++20 basic_string& operator=(basic_string&& str) noexcept( allocator_type::propagate_on_container_move_assignment::value || allocator_type::is_always_equal::value ); // C++17, constexpr since C++20 basic_string& operator=(const value_type* s); // constexpr since C++20 basic_string& operator=(nullptr_t) = delete; // C++23 basic_string& operator=(value_type c); // constexpr since C++20 basic_string& operator=(initializer_list<value_type>); // constexpr since C++20 iterator begin() noexcept; // constexpr since C++20 const_iterator begin() const noexcept; // constexpr since C++20 iterator end() noexcept; // constexpr since C++20 const_iterator end() const noexcept; // constexpr since C++20 reverse_iterator rbegin() noexcept; // constexpr since C++20 const_reverse_iterator rbegin() const noexcept; // constexpr since C++20 reverse_iterator rend() noexcept; // constexpr since C++20 const_reverse_iterator rend() const noexcept; // constexpr since C++20 const_iterator cbegin() const noexcept; // constexpr since C++20 const_iterator cend() const noexcept; // constexpr since C++20 const_reverse_iterator crbegin() const noexcept; // constexpr since C++20 const_reverse_iterator crend() const noexcept; // constexpr since C++20 size_type size() const noexcept; // constexpr since C++20 size_type length() const noexcept; // constexpr since C++20 size_type max_size() const noexcept; // constexpr since C++20 size_type capacity() const noexcept; // constexpr since C++20 void resize(size_type n, value_type c); // constexpr since C++20 void resize(size_type n); // constexpr since C++20 template<class Operation> constexpr void resize_and_overwrite(size_type n, Operation op); // since C++23 void reserve(size_type res_arg); // constexpr since C++20 void reserve(); // deprecated in C++20, removed in C++26 void shrink_to_fit(); // constexpr since C++20 void clear() noexcept; // constexpr since C++20 bool empty() const noexcept; // constexpr since C++20 const_reference operator[](size_type pos) const; // constexpr since C++20 reference operator[](size_type pos); // constexpr since C++20 const_reference at(size_type n) const; // constexpr since C++20 reference at(size_type n); // constexpr since C++20 basic_string& operator+=(const basic_string& str); // constexpr since C++20 template <class T> basic_string& operator+=(const T& t); // C++17, constexpr since C++20 basic_string& operator+=(const value_type* s); // constexpr since C++20 basic_string& operator+=(value_type c); // constexpr since C++20 basic_string& operator+=(initializer_list<value_type>); // constexpr since C++20 basic_string& append(const basic_string& str); // constexpr since C++20 template <class T> basic_string& append(const T& t); // C++17, constexpr since C++20 basic_string& append(const basic_string& str, size_type pos, size_type n=npos); // C++14, constexpr since C++20 template <class T> basic_string& append(const T& t, size_type pos, size_type n=npos); // C++17, constexpr since C++20 basic_string& append(const value_type* s, size_type n); // constexpr since C++20 basic_string& append(const value_type* s); // constexpr since C++20 basic_string& append(size_type n, value_type c); // constexpr since C++20 template<class InputIterator> basic_string& append(InputIterator first, InputIterator last); // constexpr since C++20 template<container-compatible-range<charT> R> constexpr basic_string& append_range(R&& rg); // C++23 basic_string& append(initializer_list<value_type>); // constexpr since C++20 void push_back(value_type c); // constexpr since C++20 void pop_back(); // constexpr since C++20 reference front(); // constexpr since C++20 const_reference front() const; // constexpr since C++20 reference back(); // constexpr since C++20 const_reference back() const; // constexpr since C++20 basic_string& assign(const basic_string& str); // constexpr since C++20 template <class T> basic_string& assign(const T& t); // C++17, constexpr since C++20 basic_string& assign(basic_string&& str); // constexpr since C++20 basic_string& assign(const basic_string& str, size_type pos, size_type n=npos); // C++14, constexpr since C++20 template <class T> basic_string& assign(const T& t, size_type pos, size_type n=npos); // C++17, constexpr since C++20 basic_string& assign(const value_type* s, size_type n); // constexpr since C++20 basic_string& assign(const value_type* s); // constexpr since C++20 basic_string& assign(size_type n, value_type c); // constexpr since C++20 template<class InputIterator> basic_string& assign(InputIterator first, InputIterator last); // constexpr since C++20 template<container-compatible-range<charT> R> constexpr basic_string& assign_range(R&& rg); // C++23 basic_string& assign(initializer_list<value_type>); // constexpr since C++20 basic_string& insert(size_type pos1, const basic_string& str); // constexpr since C++20 template <class T> basic_string& insert(size_type pos1, const T& t); // constexpr since C++20 basic_string& insert(size_type pos1, const basic_string& str, size_type pos2, size_type n); // constexpr since C++20 template <class T> basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n); // C++17, constexpr since C++20 basic_string& insert(size_type pos, const value_type* s, size_type n=npos); // C++14, constexpr since C++20 basic_string& insert(size_type pos, const value_type* s); // constexpr since C++20 basic_string& insert(size_type pos, size_type n, value_type c); // constexpr since C++20 iterator insert(const_iterator p, value_type c); // constexpr since C++20 iterator insert(const_iterator p, size_type n, value_type c); // constexpr since C++20 template<class InputIterator> iterator insert(const_iterator p, InputIterator first, InputIterator last); // constexpr since C++20 template<container-compatible-range<charT> R> constexpr iterator insert_range(const_iterator p, R&& rg); // C++23 iterator insert(const_iterator p, initializer_list<value_type>); // constexpr since C++20 basic_string& erase(size_type pos = 0, size_type n = npos); // constexpr since C++20 iterator erase(const_iterator position); // constexpr since C++20 iterator erase(const_iterator first, const_iterator last); // constexpr since C++20 basic_string& replace(size_type pos1, size_type n1, const basic_string& str); // constexpr since C++20 template <class T> basic_string& replace(size_type pos1, size_type n1, const T& t); // C++17, constexpr since C++20 basic_string& replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2=npos); // C++14, constexpr since C++20 template <class T> basic_string& replace(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n); // C++17, constexpr since C++20 basic_string& replace(size_type pos, size_type n1, const value_type* s, size_type n2); // constexpr since C++20 basic_string& replace(size_type pos, size_type n1, const value_type* s); // constexpr since C++20 basic_string& replace(size_type pos, size_type n1, size_type n2, value_type c); // constexpr since C++20 basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); // constexpr since C++20 template <class T> basic_string& replace(const_iterator i1, const_iterator i2, const T& t); // C++17, constexpr since C++20 basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s, size_type n); // constexpr since C++20 basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s); // constexpr since C++20 basic_string& replace(const_iterator i1, const_iterator i2, size_type n, value_type c); // constexpr since C++20 template<class InputIterator> basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); // constexpr since C++20 template<container-compatible-range<charT> R> constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); // C++23 basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<value_type>); // constexpr since C++20 size_type copy(value_type* s, size_type n, size_type pos = 0) const; // constexpr since C++20 basic_string substr(size_type pos = 0, size_type n = npos) const; // constexpr in C++20, removed in C++23 basic_string substr(size_type pos = 0, size_type n = npos) const&; // since C++23 constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&; // since C++23 void swap(basic_string& str) noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value || allocator_traits<allocator_type>::is_always_equal::value); // C++17, constexpr since C++20 const value_type* c_str() const noexcept; // constexpr since C++20 const value_type* data() const noexcept; // constexpr since C++20 value_type* data() noexcept; // C++17, constexpr since C++20 allocator_type get_allocator() const noexcept; // constexpr since C++20 size_type find(const basic_string& str, size_type pos = 0) const noexcept; // constexpr since C++20 template <class T> size_type find(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type find(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type find(const value_type* s, size_type pos = 0) const noexcept; // constexpr since C++20 size_type find(value_type c, size_type pos = 0) const noexcept; // constexpr since C++20 size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; // constexpr since C++20 template <class T> size_type rfind(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type rfind(const value_type* s, size_type pos = npos) const noexcept; // constexpr since C++20 size_type rfind(value_type c, size_type pos = npos) const noexcept; // constexpr since C++20 size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; // constexpr since C++20 template <class T> size_type find_first_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept; // constexpr since C++20 size_type find_first_of(value_type c, size_type pos = 0) const noexcept; // constexpr since C++20 size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept; // constexpr since C++20 template <class T> size_type find_last_of(const T& t, size_type pos = npos) const noexcept noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept; // constexpr since C++20 size_type find_last_of(value_type c, size_type pos = npos) const noexcept; // constexpr since C++20 size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept; // constexpr since C++20 template <class T> size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept; // constexpr since C++20 size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept; // constexpr since C++20 size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept; // constexpr since C++20 template <class T> size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept; // constexpr since C++20 size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept; // constexpr since C++20 size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept; // constexpr since C++20 int compare(const basic_string& str) const noexcept; // constexpr since C++20 template <class T> int compare(const T& t) const noexcept; // C++17, noexcept as an extension, constexpr since C++20 int compare(size_type pos1, size_type n1, const basic_string& str) const; // constexpr since C++20 template <class T> int compare(size_type pos1, size_type n1, const T& t) const; // C++17, constexpr since C++20 int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2=npos) const; // C++14, constexpr since C++20 template <class T> int compare(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n2=npos) const; // C++17, constexpr since C++20 int compare(const value_type* s) const noexcept; // constexpr since C++20 int compare(size_type pos1, size_type n1, const value_type* s) const; // constexpr since C++20 int compare(size_type pos1, size_type n1, const value_type* s, size_type n2) const; // constexpr since C++20 constexpr bool starts_with(basic_string_view<charT, traits> sv) const noexcept; // C++20 constexpr bool starts_with(charT c) const noexcept; // C++20 constexpr bool starts_with(const charT* s) const; // C++20 constexpr bool ends_with(basic_string_view<charT, traits> sv) const noexcept; // C++20 constexpr bool ends_with(charT c) const noexcept; // C++20 constexpr bool ends_with(const charT* s) const; // C++20 constexpr bool contains(basic_string_view<charT, traits> sv) const noexcept; // C++23 constexpr bool contains(charT c) const noexcept; // C++23 constexpr bool contains(const charT* s) const; // C++23 }; template<class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>> basic_string(InputIterator, InputIterator, Allocator = Allocator()) -> basic_string<typename iterator_traits<InputIterator>::value_type, char_traits<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17 template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> basic_string(from_range_t, R&&, Allocator = Allocator()) -> basic_string<ranges::range_value_t<R>, char_traits<ranges::range_value_t<R>>, Allocator>; // C++23 template<class charT, class traits, class Allocator = allocator<charT>> explicit basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator()) -> basic_string<charT, traits, Allocator>; // C++17 template<class charT, class traits, class Allocator = allocator<charT>> basic_string(basic_string_view<charT, traits>, typename see below::size_type, typename see below::size_type, const Allocator& = Allocator()) -> basic_string<charT, traits, Allocator>; // C++17 template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs); // constexpr since C++20 template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const charT* lhs , const basic_string<charT,traits,Allocator>&rhs); // constexpr since C++20 template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(charT lhs, const basic_string<charT,traits,Allocator>& rhs); // constexpr since C++20 template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs); // constexpr since C++20 template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs); // constexpr since C++20 template<class charT, class traits, class Allocator> bool operator==(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // constexpr since C++20 template<class charT, class traits, class Allocator> bool operator==(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator==(const basic_string<charT,traits,Allocator>& lhs, const charT* rhs) noexcept; // constexpr since C++20 template<class charT, class traits, class Allocator> bool operator!=(const basic_string<charT,traits,Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator!=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator!=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator< (const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator< (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator< (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator> (const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator> (const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator> (const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator<=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator<=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator>=(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> bool operator>=(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; // removed in C++20 template<class charT, class traits, class Allocator> // since C++20 constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; template<class charT, class traits, class Allocator> // since C++20 constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs) noexcept; template<class charT, class traits, class Allocator> void swap(basic_string<charT, traits, Allocator>& lhs, basic_string<charT, traits, Allocator>& rhs) noexcept(noexcept(lhs.swap(rhs))); // constexpr since C++20 template<class charT, class traits, class Allocator> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str); template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str); template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str, charT delim); template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str); template<class charT, class traits, class Allocator, class U> typename basic_string<charT, traits, Allocator>::size_type erase(basic_string<charT, traits, Allocator>& c, const U& value); // C++20 template<class charT, class traits, class Allocator, class Predicate> typename basic_string<charT, traits, Allocator>::size_type erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20 typedef basic_string<char> string; typedef basic_string<wchar_t> wstring; typedef basic_string<char8_t> u8string; // C++20 typedef basic_string<char16_t> u16string; typedef basic_string<char32_t> u32string; int stoi (const string& str, size_t* idx = nullptr, int base = 10); long stol (const string& str, size_t* idx = nullptr, int base = 10); unsigned long stoul (const string& str, size_t* idx = nullptr, int base = 10); long long stoll (const string& str, size_t* idx = nullptr, int base = 10); unsigned long long stoull(const string& str, size_t* idx = nullptr, int base = 10); float stof (const string& str, size_t* idx = nullptr); double stod (const string& str, size_t* idx = nullptr); long double stold(const string& str, size_t* idx = nullptr); string to_string(int val); string to_string(unsigned val); string to_string(long val); string to_string(unsigned long val); string to_string(long long val); string to_string(unsigned long long val); string to_string(float val); string to_string(double val); string to_string(long double val); int stoi (const wstring& str, size_t* idx = nullptr, int base = 10); long stol (const wstring& str, size_t* idx = nullptr, int base = 10); unsigned long stoul (const wstring& str, size_t* idx = nullptr, int base = 10); long long stoll (const wstring& str, size_t* idx = nullptr, int base = 10); unsigned long long stoull(const wstring& str, size_t* idx = nullptr, int base = 10); float stof (const wstring& str, size_t* idx = nullptr); double stod (const wstring& str, size_t* idx = nullptr); long double stold(const wstring& str, size_t* idx = nullptr); wstring to_wstring(int val); wstring to_wstring(unsigned val); wstring to_wstring(long val); wstring to_wstring(unsigned long val); wstring to_wstring(long long val); wstring to_wstring(unsigned long long val); wstring to_wstring(float val); wstring to_wstring(double val); wstring to_wstring(long double val); template <> struct hash<string>; template <> struct hash<u8string>; // C++20 template <> struct hash<u16string>; template <> struct hash<u32string>; template <> struct hash<wstring>; basic_string<char> operator""s( const char *str, size_t len ); // C++14, constexpr since C++20 basic_string<wchar_t> operator""s( const wchar_t *str, size_t len ); // C++14, constexpr since C++20 constexpr basic_string<char8_t> operator""s( const char8_t *str, size_t len ); // C++20 basic_string<char16_t> operator""s( const char16_t *str, size_t len ); // C++14, constexpr since C++20 basic_string<char32_t> operator""s( const char32_t *str, size_t len ); // C++14, constexpr since C++20 } // std */ // clang-format on #include <__algorithm/max.h> #include <__algorithm/min.h> #include <__algorithm/remove.h> #include <__algorithm/remove_if.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__format/enable_insertable.h> #include <__functional/hash.h> #include <__functional/unary_function.h> #include <__fwd/string.h> #include <__ios/fpos.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> #include <__iterator/wrap_iter.h> #include <__memory/addressof.h> #include <__memory/allocate_at_least.h> #include <__memory/allocator.h> #include <__memory/allocator_traits.h> #include <__memory/compressed_pair.h> #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> #include <__memory/swap_allocator.h> #include <__memory_resource/polymorphic_allocator.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/container_compatible_range.h> #include <__ranges/from_range.h> #include <__ranges/size.h> #include <__string/char_traits.h> #include <__string/extern_template_lists.h> #include <__type_traits/is_allocator.h> #include <__type_traits/is_array.h> #include <__type_traits/is_convertible.h> #include <__type_traits/is_nothrow_default_constructible.h> #include <__type_traits/is_nothrow_move_assignable.h> #include <__type_traits/is_same.h> #include <__type_traits/is_standard_layout.h> #include <__type_traits/is_trivial.h> #include <__type_traits/noexcept_move_assign_container.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/void_t.h> #include <__utility/auto_cast.h> #include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/is_pointer_in_range.h> #include <__utility/move.h> #include <__utility/swap.h> #include <__utility/unreachable.h> #include <climits> #include <cstdio> // EOF #include <cstring> #include <limits> #include <stdexcept> #include <string_view> #include <version> #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS # include <cwchar> #endif // standard-mandated includes // [iterator.range] #include <__iterator/access.h> #include <__iterator/data.h> #include <__iterator/empty.h> #include <__iterator/reverse_access.h> #include <__iterator/size.h> // [string.syn] #include <compare> #include <initializer_list> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) # define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS __attribute__((__no_sanitize__("address"))) // This macro disables AddressSanitizer (ASan) instrumentation for a specific function, // allowing memory accesses that would normally trigger ASan errors to proceed without crashing. // This is useful for accessing parts of objects memory, which should not be accessed, // such as unused bytes in short strings, that should never be accessed // by other parts of the program. #else # define _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS #endif #define _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED false _LIBCPP_BEGIN_NAMESPACE_STD // basic_string template <class _CharT, class _Traits, class _Allocator> basic_string<_CharT, _Traits, _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const basic_string<_CharT, _Traits, _Allocator>& __y); template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const _CharT* __x, const basic_string<_CharT, _Traits, _Allocator>& __y); template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(_CharT __x, const basic_string<_CharT, _Traits, _Allocator>& __y); template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const _CharT* __y); template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, _CharT __y); extern template _LIBCPP_EXPORTED_FROM_ABI string operator+ <char, char_traits<char>, allocator<char> >(char const*, string const&); template <class _Iter> struct __string_is_trivial_iterator : public false_type {}; template <class _Tp> struct __string_is_trivial_iterator<_Tp*> : public is_arithmetic<_Tp> {}; template <class _Iter> struct __string_is_trivial_iterator<__wrap_iter<_Iter> > : public __string_is_trivial_iterator<_Iter> {}; template <class _CharT, class _Traits, class _Tp> struct __can_be_converted_to_string_view : public _BoolConstant< is_convertible<const _Tp&, basic_string_view<_CharT, _Traits> >::value && !is_convertible<const _Tp&, const _CharT*>::value > {}; struct __uninitialized_size_tag {}; struct __init_with_sentinel_tag {}; template <class _CharT, class _Traits, class _Allocator> class basic_string { private: using __default_allocator_type = allocator<_CharT>; public: typedef basic_string __self; typedef basic_string_view<_CharT, _Traits> __self_view; typedef _Traits traits_type; typedef _CharT value_type; typedef _Allocator allocator_type; typedef allocator_traits<allocator_type> __alloc_traits; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; static_assert((!is_array<value_type>::value), "Character type of basic_string must not be an array"); static_assert((is_standard_layout<value_type>::value), "Character type of basic_string must be standard-layout"); static_assert((is_trivial<value_type>::value), "Character type of basic_string must be trivial"); static_assert((is_same<_CharT, typename traits_type::char_type>::value), "traits_type::char_type must be the same type as CharT"); static_assert((is_same<typename allocator_type::value_type, value_type>::value), "Allocator::value_type must be same type as value_type"); static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value, "[allocator.requirements] states that rebinding an allocator to the same type should result in the " "original allocator"); // TODO: Implement iterator bounds checking without requiring the global database. typedef __wrap_iter<pointer> iterator; typedef __wrap_iter<const_pointer> const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; private: static_assert(CHAR_BIT == 8, "This implementation assumes that one byte contains 8 bits"); #ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT struct __long { pointer __data_; size_type __size_; size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1; size_type __is_long_ : 1; }; enum { __min_cap = (sizeof(__long) - 1) / sizeof(value_type) > 2 ? (sizeof(__long) - 1) / sizeof(value_type) : 2 }; struct __short { value_type __data_[__min_cap]; unsigned char __padding_[sizeof(value_type) - 1]; unsigned char __size_ : 7; unsigned char __is_long_ : 1; }; // The __endian_factor is required because the field we use to store the size // has one fewer bit than it would if it were not a bitfield. // // If the LSB is used to store the short-flag in the short string representation, // we have to multiply the size by two when it is stored and divide it by two when // it is loaded to make sure that we always store an even number. In the long string // representation, we can ignore this because we can assume that we always allocate // an even amount of value_types. // // If the MSB is used for the short-flag, the max_size() is numeric_limits<size_type>::max() / 2. // This does not impact the short string representation, since we never need the MSB // for representing the size of a short string anyway. # ifdef _LIBCPP_BIG_ENDIAN static const size_type __endian_factor = 2; # else static const size_type __endian_factor = 1; # endif #else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT # ifdef _LIBCPP_BIG_ENDIAN static const size_type __endian_factor = 1; # else static const size_type __endian_factor = 2; # endif // Attribute 'packed' is used to keep the layout compatible with the // previous definition that did not use bit fields. This is because on // some platforms bit fields have a default size rather than the actual // size used, e.g., it is 4 bytes on AIX. See D128285 for details. struct __long { struct _LIBCPP_PACKED { size_type __is_long_ : 1; size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1; }; size_type __size_; pointer __data_; }; enum { __min_cap = (sizeof(__long) - 1) / sizeof(value_type) > 2 ? (sizeof(__long) - 1) / sizeof(value_type) : 2 }; struct __short { struct _LIBCPP_PACKED { unsigned char __is_long_ : 1; unsigned char __size_ : 7; }; char __padding_[sizeof(value_type) - 1]; value_type __data_[__min_cap]; }; #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size."); union __ulx { __long __lx; __short __lxx; }; enum { __n_words = sizeof(__ulx) / sizeof(size_type) }; struct __raw { size_type __words[__n_words]; }; struct __rep { union { __short __s; __long __l; __raw __r; }; }; __compressed_pair<__rep, allocator_type> __r_; // Construct a string with the given allocator and enough storage to hold `__size` characters, but // don't initialize the characters. The contents of the string, including the null terminator, must be // initialized separately. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string( __uninitialized_size_tag, size_type __size, const allocator_type& __a) : __r_(__default_init_tag(), __a) { if (__size > max_size()) __throw_length_error(); if (__fits_in_sso(__size)) { __r_.first() = __rep(); __set_short_size(__size); } else { auto __capacity = __recommend(__size) + 1; auto __allocation = __alloc_traits::allocate(__alloc(), __capacity); __begin_lifetime(__allocation, __capacity); __set_long_cap(__capacity); __set_long_pointer(__allocation); __set_long_size(__size); } __annotate_new(__size); } template <class _Iter, class _Sent> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(__init_with_sentinel_tag, _Iter __first, _Sent __last, const allocator_type& __a) : __r_(__default_init_tag(), __a) { __init_with_sentinel(std::move(__first), std::move(__last)); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __make_iterator(pointer __p) { return iterator(__p); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator __make_const_iterator(const_pointer __p) const { return const_iterator(__p); } public: _LIBCPP_TEMPLATE_DATA_VIS static const size_type npos = -1; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) : __r_(__value_init_tag(), __default_init_tag()) { __annotate_new(0); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value) #else _NOEXCEPT #endif : __r_(__value_init_tag(), __a) { __annotate_new(0); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string(const basic_string& __str) : __r_(__default_init_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc())) { if (!__str.__is_long()) { __r_.first() = __str.__r_.first(); __annotate_new(__get_short_size()); } else __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string(const basic_string& __str, const allocator_type& __a) : __r_(__default_init_tag(), __a) { if (!__str.__is_long()) { __r_.first() = __str.__r_.first(); __annotate_new(__get_short_size()); } else __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str) # if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value) # else _NOEXCEPT # endif // Turning off ASan instrumentation for variable initialization with _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS // does not work consistently during initialization of __r_, so we instead unpoison __str's memory manually first. // __str's memory needs to be unpoisoned only in the case where it's a short string. : __r_(((__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_))) { __str.__r_.first() = __rep(); __str.__annotate_new(0); if (!__is_long()) __annotate_new(size()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str, const allocator_type& __a) : __r_(__default_init_tag(), __a) { if (__str.__is_long() && __a != __str.__alloc()) // copy, not move __init(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); else { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); if (!__str.__is_long()) __str.__annotate_delete(); __r_.first() = __str.__r_.first(); __str.__r_.first() = __rep(); __str.__annotate_new(0); if (!__is_long() && this != &__str) __annotate_new(size()); } } #endif // _LIBCPP_CXX03_LANG template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s) : __r_(__default_init_tag(), __default_init_tag()) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "basic_string(const char*) detected nullptr"); __init(__s, traits_type::length(__s)); } template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, const _Allocator& __a) : __r_(__default_init_tag(), __a) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "basic_string(const char*, allocator) detected nullptr"); __init(__s, traits_type::length(__s)); } #if _LIBCPP_STD_VER >= 23 basic_string(nullptr_t) = delete; #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n) : __r_(__default_init_tag(), __default_init_tag()) { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr"); __init(__s, __n); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n, const _Allocator& __a) : __r_(__default_init_tag(), __a) { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr"); __init(__s, __n); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c) : __r_(__default_init_tag(), __default_init_tag()) { __init(__n, __c); } #if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr basic_string( basic_string&& __str, size_type __pos, const _Allocator& __alloc = _Allocator()) : basic_string(std::move(__str), __pos, npos, __alloc) {} _LIBCPP_HIDE_FROM_ABI constexpr basic_string( basic_string&& __str, size_type __pos, size_type __n, const _Allocator& __alloc = _Allocator()) : __r_(__default_init_tag(), __alloc) { if (__pos > __str.size()) __throw_out_of_range(); auto __len = std::min<size_type>(__n, __str.size() - __pos); if (__alloc_traits::is_always_equal::value || __alloc == __str.__alloc()) { __move_assign(std::move(__str), __pos, __len); } else { // Perform a copy because the allocators are not compatible. __init(__str.data() + __pos, __len); } } #endif template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c, const _Allocator& __a) : __r_(__default_init_tag(), __a) { __init(__n, __c); } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Allocator& __a = _Allocator()) : __r_(__default_init_tag(), __a) { size_type __str_sz = __str.size(); if (__pos > __str_sz) __throw_out_of_range(); __init(__str.data() + __pos, std::min(__n, __str_sz - __pos)); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a = _Allocator()) : __r_(__default_init_tag(), __a) { size_type __str_sz = __str.size(); if (__pos > __str_sz) __throw_out_of_range(); __init(__str.data() + __pos, __str_sz - __pos); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type()) : __r_(__default_init_tag(), __a) { __self_view __sv0 = __t; __self_view __sv = __sv0.substr(__pos, __n); __init(__sv.data(), __sv.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t) : __r_(__default_init_tag(), __default_init_tag()) { __self_view __sv = __t; __init(__sv.data(), __sv.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string( const _Tp& __t, const allocator_type& __a) : __r_(__default_init_tag(), __a) { __self_view __sv = __t; __init(__sv.data(), __sv.size()); } template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(_InputIterator __first, _InputIterator __last) : __r_(__default_init_tag(), __default_init_tag()) { __init(__first, __last); } template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : __r_(__default_init_tag(), __a) { __init(__first, __last); } #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> _LIBCPP_HIDE_FROM_ABI constexpr basic_string( from_range_t, _Range&& __range, const allocator_type& __a = allocator_type()) : __r_(__default_init_tag(), __a) { if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { __init_with_size(ranges::begin(__range), ranges::end(__range), ranges::distance(__range)); } else { __init_with_sentinel(ranges::begin(__range), ranges::end(__range)); } } #endif #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il) : __r_(__default_init_tag(), __default_init_tag()) { __init(__il.begin(), __il.end()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il, const _Allocator& __a) : __r_(__default_init_tag(), __a) { __init(__il.begin(), __il.end()); } #endif // _LIBCPP_CXX03_LANG inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string() { __annotate_delete(); if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string& operator=(const basic_string& __str); template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const _Tp& __t) { __self_view __sv = __t; return assign(__sv); } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(basic_string&& __str) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) { __move_assign(__str, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>()); return *this; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(initializer_list<value_type> __il) { return assign(__il.begin(), __il.size()); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const value_type* __s) { return assign(__s); } #if _LIBCPP_STD_VER >= 23 basic_string& operator=(nullptr_t) = delete; #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string& operator=(value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator begin() _NOEXCEPT { return __make_iterator(__get_pointer()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator begin() const _NOEXCEPT { return __make_const_iterator(__get_pointer()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator end() _NOEXCEPT { return __make_iterator(__get_pointer() + size()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator end() const _NOEXCEPT { return __make_const_iterator(__get_pointer() + size()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rbegin() const _NOEXCEPT { return const_reverse_iterator(end()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reverse_iterator rend() _NOEXCEPT { return reverse_iterator(begin()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator rend() const _NOEXCEPT { return const_reverse_iterator(begin()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cbegin() const _NOEXCEPT { return begin(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator cend() const _NOEXCEPT { return end(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crbegin() const _NOEXCEPT { return rbegin(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reverse_iterator crend() const _NOEXCEPT { return rend(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type size() const _NOEXCEPT { return __is_long() ? __get_long_size() : __get_short_size(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type length() const _NOEXCEPT { return size(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type max_size() const _NOEXCEPT { size_type __m = __alloc_traits::max_size(__alloc()); if (__m <= std::numeric_limits<size_type>::max() / 2) { return __m - __alignment; } else { bool __uses_lsb = __endian_factor == 2; return __uses_lsb ? __m - __alignment : (__m / 2) - __alignment; } } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type capacity() const _NOEXCEPT { return (__is_long() ? __get_long_cap() : static_cast<size_type>(__min_cap)) - 1; } _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __n, value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __n) { resize(__n, value_type()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 void reserve(size_type __requested_capacity); #if _LIBCPP_STD_VER >= 23 template <class _Op> _LIBCPP_HIDE_FROM_ABI constexpr void resize_and_overwrite(size_type __n, _Op __op) { __resize_default_init(__n); __erase_to_end(std::move(__op)(data(), _LIBCPP_AUTO_CAST(__n))); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __resize_default_init(size_type __n); #if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_STRING_RESERVE) _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve() _NOEXCEPT { shrink_to_fit(); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void shrink_to_fit() _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void clear() _NOEXCEPT; _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool empty() const _NOEXCEPT { return size() == 0; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds"); if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) { return *(__get_long_pointer() + __pos); } return *(data() + __pos); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __pos) _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds"); if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) { return *(__get_long_pointer() + __pos); } return *(__get_pointer() + __pos); } _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference at(size_type __n) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 reference at(size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const basic_string& __str) { return append(__str); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string >::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const _Tp& __t) { __self_view __sv = __t; return append(__sv); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const value_type* __s) { return append(__s); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(value_type __c) { push_back(__c); return *this; } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(initializer_list<value_type> __il) { return append(__il); } #endif // _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const basic_string& __str) { return append(__str.data(), __str.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const _Tp& __t) { __self_view __sv = __t; return append(__sv.data(), __sv.size()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const basic_string& __str, size_type __pos, size_type __n = npos); template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const _Tp& __t, size_type __pos, size_type __n = npos); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(size_type __n, value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __append_default_init(size_type __n); template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(_InputIterator __first, _InputIterator __last) { const basic_string __temp(__first, __last, __alloc()); append(__temp.data(), __temp.size()); return *this; } template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(_ForwardIterator __first, _ForwardIterator __last); #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> _LIBCPP_HIDE_FROM_ABI constexpr basic_string& append_range(_Range&& __range) { insert_range(end(), std::forward<_Range>(__range)); return *this; } #endif #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(initializer_list<value_type> __il) { return append(__il.begin(), __il.size()); } #endif // _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back(); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty"); return *__get_pointer(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty"); return *data(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty"); return *(__get_pointer() + size() - 1); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty"); return *(data() + size() - 1); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const _Tp& __t) { __self_view __sv = __t; return assign(__sv.data(), __sv.size()); } #if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr void __move_assign(basic_string&& __str, size_type __pos, size_type __len) { // Pilfer the allocation from __str. _LIBCPP_ASSERT_INTERNAL(__alloc() == __str.__alloc(), "__move_assign called with wrong allocator"); size_type __old_sz = __str.size(); if (!__str.__is_long()) __str.__annotate_delete(); __r_.first() = __str.__r_.first(); __str.__r_.first() = __rep(); __str.__annotate_new(0); _Traits::move(data(), data() + __pos, __len); __set_size(__len); _Traits::assign(data()[__len], value_type()); if (!__is_long()) { __annotate_new(__len); } else if (__old_sz > __len) { __annotate_shrink(__old_sz); } } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const basic_string& __str) { return *this = __str; } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(basic_string&& __str) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) { *this = std::move(__str); return *this; } #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const basic_string& __str, size_type __pos, size_type __n = npos); template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const _Tp& __t, size_type __pos, size_type __n = npos); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(size_type __n, value_type __c); template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(_InputIterator __first, _InputIterator __last); template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(_ForwardIterator __first, _ForwardIterator __last); #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> _LIBCPP_HIDE_FROM_ABI constexpr basic_string& assign_range(_Range&& __range) { if constexpr (__string_is_trivial_iterator<ranges::iterator_t<_Range>>::value && (ranges::forward_range<_Range> || ranges::sized_range<_Range>)) { size_type __n = static_cast<size_type>(ranges::distance(__range)); __assign_trivial(ranges::begin(__range), ranges::end(__range), __n); } else { __assign_with_sentinel(ranges::begin(__range), ranges::end(__range)); } return *this; } #endif #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(initializer_list<value_type> __il) { return assign(__il.begin(), __il.size()); } #endif // _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const basic_string& __str) { return insert(__pos1, __str.data(), __str.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const _Tp& __t) { __self_view __sv = __t; return insert(__pos1, __sv.data(), __sv.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n = npos); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n = npos); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, size_type __n, value_type __c); _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, value_type __c); #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> _LIBCPP_HIDE_FROM_ABI constexpr iterator insert_range(const_iterator __position, _Range&& __range) { if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { auto __n = static_cast<size_type>(ranges::distance(__range)); return __insert_with_size(__position, ranges::begin(__range), ranges::end(__range), __n); } else { basic_string __temp(from_range, std::forward<_Range>(__range), __alloc()); return insert(__position, __temp.data(), __temp.data() + __temp.size()); } } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, size_type __n, value_type __c) { difference_type __p = __pos - begin(); insert(static_cast<size_type>(__p), __n, __c); return begin() + __p; } template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, _InputIterator __first, _InputIterator __last); template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, initializer_list<value_type> __il) { return insert(__pos, __il.begin(), __il.end()); } #endif // _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& erase(size_type __pos = 0, size_type __n = npos); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator erase(const_iterator __pos); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator erase(const_iterator __first, const_iterator __last); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str) { return replace(__pos1, __n1, __str.data(), __str.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos1, size_type __n1, const _Tp& __t) { __self_view __sv = __t; return replace(__pos1, __n1, __sv.data(), __sv.size()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos); template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const basic_string& __str) { return replace( static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __str.data(), __str.size()); } template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) { __self_view __sv = __t; return replace(__i1 - begin(), __i2 - __i1, __sv); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n) { return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __s, __n); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const value_type* __s) { return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __s); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c) { return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __n, __c); } template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2); #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> _LIBCPP_HIDE_FROM_ABI constexpr basic_string& replace_with_range(const_iterator __i1, const_iterator __i2, _Range&& __range) { basic_string __temp(from_range, std::forward<_Range>(__range), __alloc()); return replace(__i1, __i2, __temp); } #endif #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, initializer_list<value_type> __il) { return replace(__i1, __i2, __il.begin(), __il.end()); } #endif // _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const; #if _LIBCPP_STD_VER <= 20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string substr(size_type __pos = 0, size_type __n = npos) const { return basic_string(*this, __pos, __n); } #else _LIBCPP_HIDE_FROM_ABI constexpr basic_string substr(size_type __pos = 0, size_type __n = npos) const& { return basic_string(*this, __pos, __n); } _LIBCPP_HIDE_FROM_ABI constexpr basic_string substr(size_type __pos = 0, size_type __n = npos) && { return basic_string(std::move(*this), __pos, __n); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(basic_string& __str) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value); #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* c_str() const _NOEXCEPT { return data(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* data() const _NOEXCEPT { return std::__to_address(__get_pointer()); } #if _LIBCPP_STD_VER >= 17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 value_type* data() _NOEXCEPT { return std::__to_address(__get_pointer()); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator_type get_allocator() const _NOEXCEPT { return __alloc(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(value_type __c, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(value_type __c, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(value_type __c, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(value_type __c, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(value_type __c, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(value_type __c, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const basic_string& __str) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const _Tp& __t) const _NOEXCEPT; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const _Tp& __t) const; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const basic_string& __str) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos) const; template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const value_type* __s) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const value_type* __s) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const; #if _LIBCPP_STD_VER >= 20 constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(__self_view __sv) const noexcept { return __self_view(data(), size()).starts_with(__sv); } constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(value_type __c) const noexcept { return !empty() && _Traits::eq(front(), __c); } constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(const value_type* __s) const noexcept { return starts_with(__self_view(__s)); } constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(__self_view __sv) const noexcept { return __self_view(data(), size()).ends_with(__sv); } constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(value_type __c) const noexcept { return !empty() && _Traits::eq(back(), __c); } constexpr _LIBCPP_HIDE_FROM_ABI bool ends_with(const value_type* __s) const noexcept { return ends_with(__self_view(__s)); } #endif #if _LIBCPP_STD_VER >= 23 constexpr _LIBCPP_HIDE_FROM_ABI bool contains(__self_view __sv) const noexcept { return __self_view(data(), size()).contains(__sv); } constexpr _LIBCPP_HIDE_FROM_ABI bool contains(value_type __c) const noexcept { return __self_view(data(), size()).contains(__c); } constexpr _LIBCPP_HIDE_FROM_ABI bool contains(const value_type* __s) const { return __self_view(data(), size()).contains(__s); } #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __invariants() const; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __clear_and_shrink() _NOEXCEPT; private: template <class _Alloc> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool friend operator==(const basic_string<char, char_traits<char>, _Alloc>& __lhs, const basic_string<char, char_traits<char>, _Alloc>& __rhs) _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __shrink_or_extend(size_type __target_capacity); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS bool __is_long() const _NOEXCEPT { if (__libcpp_is_constant_evaluated() && __builtin_constant_p(__r_.first().__l.__is_long_)) { return __r_.first().__l.__is_long_; } return __r_.first().__s.__is_long_; } static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __begin_lifetime(pointer __begin, size_type __n) { #if _LIBCPP_STD_VER >= 20 if (__libcpp_is_constant_evaluated()) { for (size_type __i = 0; __i != __n; ++__i) std::construct_at(std::addressof(__begin[__i])); } #else (void)__begin; (void)__n; #endif // _LIBCPP_STD_VER >= 20 } _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI static bool __fits_in_sso(size_type __sz) { return __sz < __min_cap; } template <class _Iterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign_trivial(_Iterator __first, _Sentinel __last, size_type __n); template <class _Iterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_Iterator __first, _Sentinel __last); template <class _ForwardIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 iterator __insert_from_safe_copy(size_type __n, size_type __ip, _ForwardIterator __first, _Sentinel __last) { size_type __sz = size(); size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { __annotate_increase(__n); __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) traits_type::move(__p + __ip + __n, __p + __ip, __n_move); } else { __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __ip, 0, __n); __p = std::__to_address(__get_long_pointer()); } __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); for (__p += __ip; __first != __last; ++__p, ++__first) traits_type::assign(*__p, *__first); return begin() + __ip; } template <class _Iterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __insert_with_size(const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 allocator_type& __alloc() _NOEXCEPT { return __r_.second(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const allocator_type& __alloc() const _NOEXCEPT { return __r_.second(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS void __set_short_size(size_type __s) _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(__s < __min_cap, "__s should never be greater than or equal to the short string capacity"); __r_.first().__s.__size_ = __s; __r_.first().__s.__is_long_ = false; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS size_type __get_short_size() const _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL(!__r_.first().__s.__is_long_, "String has to be short when trying to get the short size"); return __r_.first().__s.__size_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_size(size_type __s) _NOEXCEPT { __r_.first().__l.__size_ = __s; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_long_size() const _NOEXCEPT { return __r_.first().__l.__size_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_size(size_type __s) _NOEXCEPT { if (__is_long()) __set_long_size(__s); else __set_short_size(__s); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_cap(size_type __s) _NOEXCEPT { __r_.first().__l.__cap_ = __s / __endian_factor; __r_.first().__l.__is_long_ = true; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_long_cap() const _NOEXCEPT { return __r_.first().__l.__cap_ * __endian_factor; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_pointer(pointer __p) _NOEXCEPT { __r_.first().__l.__data_ = __p; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_long_pointer() _NOEXCEPT { return __r_.first().__l.__data_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_long_pointer() const _NOEXCEPT { return __r_.first().__l.__data_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_short_pointer() _NOEXCEPT { return pointer_traits<pointer>::pointer_to(__r_.first().__s.__data_[0]); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_short_pointer() const _NOEXCEPT { return pointer_traits<const_pointer>::pointer_to(__r_.first().__s.__data_[0]); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_pointer() _NOEXCEPT { return __is_long() ? __get_long_pointer() : __get_short_pointer(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_pointer() const _NOEXCEPT { return __is_long() ? __get_long_pointer() : __get_short_pointer(); } // The following functions are no-ops outside of AddressSanitizer mode. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_contiguous_container(const void* __old_mid, const void* __new_mid) const { (void)__old_mid; (void)__new_mid; #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) const void* __begin = data(); const void* __end = data() + capacity() + 1; if (!__libcpp_is_constant_evaluated() && __begin != nullptr && is_same<allocator_type, __default_allocator_type>::value) __sanitizer_annotate_contiguous_container(__begin, __end, __old_mid, __new_mid); #endif } // ASan: short string is poisoned if and only if this function returns true. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __asan_short_string_is_annotated() const _NOEXCEPT { return _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED && !__libcpp_is_constant_evaluated(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_new(size_type __current_size) const _NOEXCEPT { (void) __current_size; #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long())) __annotate_contiguous_container(data() + capacity() + 1, data() + __current_size + 1); #endif } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_delete() const _NOEXCEPT { #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long())) __annotate_contiguous_container(data() + size() + 1, data() + capacity() + 1); #endif } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_increase(size_type __n) const _NOEXCEPT { (void) __n; #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long())) __annotate_contiguous_container(data() + size() + 1, data() + size() + 1 + __n); #endif } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_shrink(size_type __old_size) const _NOEXCEPT { (void) __old_size; #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN) if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long())) __annotate_contiguous_container(data() + __old_size + 1, data() + size() + 1); #endif } template <size_type __a> static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __align_it(size_type __s) _NOEXCEPT { return (__s + (__a - 1)) & ~(__a - 1); } enum { __alignment = #ifdef _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT 8 #else 16 #endif }; static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __recommend(size_type __s) _NOEXCEPT { if (__s < __min_cap) { return static_cast<size_type>(__min_cap) - 1; } size_type __guess = __align_it < sizeof(value_type) < __alignment ? __alignment / sizeof(value_type) : 1 > (__s + 1) - 1; if (__guess == __min_cap) ++__guess; return __guess; } inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(const value_type* __s, size_type __sz, size_type __reserve); inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(const value_type* __s, size_type __sz); inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(size_type __n, value_type __c); // Slow path for the (inlined) copy constructor for 'long' strings. // Always externally instantiated and not inlined. // Requires that __s is zero terminated. // The main reason for this function to exist is because for unstable, we // want to allow inlining of the copy constructor. However, we don't want // to call the __init() functions as those are marked as inline which may // result in over-aggressive inlining by the compiler, where our aim is // to only inline the fast path code directly in the ctor. _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void __init_copy_ctor_external(const value_type* __s, size_type __sz); template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(_InputIterator __first, _InputIterator __last); template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(_ForwardIterator __first, _ForwardIterator __last); template <class _InputIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init_with_sentinel(_InputIterator __first, _Sentinel __last); template <class _InputIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init_with_size(_InputIterator __first, _Sentinel __last, size_type __sz); _LIBCPP_CONSTEXPR_SINCE_CXX20 #if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1 _LIBCPP_HIDE_FROM_ABI #endif _LIBCPP_DEPRECATED_("use __grow_by_without_replace") void __grow_by( size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add = 0); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __grow_by_without_replace( size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add = 0); _LIBCPP_CONSTEXPR_SINCE_CXX20 void __grow_by_and_replace( size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add, const value_type* __p_new_stuff); // __assign_no_alias is invoked for assignment operations where we // have proof that the input does not alias the current instance. // For example, operator=(basic_string) performs a 'self' check. template <bool __is_short> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_no_alias(const value_type* __s, size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __erase_to_end(size_type __pos) { __null_terminate_at(std::__to_address(__get_pointer()), __pos); } // __erase_external_with_move is invoked for erase() invocations where // `n ~= npos`, likely requiring memory moves on the string data. _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void __erase_external_with_move(size_type __pos, size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const basic_string& __str) { __copy_assign_alloc( __str, integral_constant<bool, __alloc_traits::propagate_on_container_copy_assignment::value>()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const basic_string& __str, true_type) { if (__alloc() == __str.__alloc()) __alloc() = __str.__alloc(); else { if (!__str.__is_long()) { __clear_and_shrink(); __alloc() = __str.__alloc(); } else { __annotate_delete(); allocator_type __a = __str.__alloc(); auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap()); __begin_lifetime(__allocation.ptr, __allocation.count); if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); __alloc() = std::move(__a); __set_long_pointer(__allocation.ptr); __set_long_cap(__allocation.count); __set_long_size(__str.size()); __annotate_new(__get_long_size()); } } } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const basic_string&, false_type) _NOEXCEPT {} #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign(basic_string& __str, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS void __move_assign(basic_string& __str, true_type) # if _LIBCPP_STD_VER >= 17 _NOEXCEPT; # else _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value); # endif #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(basic_string& __str) _NOEXCEPT_(!__alloc_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable<allocator_type>::value) { __move_assign_alloc( __str, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(basic_string& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) { __alloc() = std::move(__c.__alloc()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(basic_string&, false_type) _NOEXCEPT {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_external(const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_external(const value_type* __s, size_type __n); // Assigns the value in __s, guaranteed to be __n < __min_cap in length. inline _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __assign_short(const value_type* __s, size_type __n) { size_type __old_size = size(); if (__n > __old_size) __annotate_increase(__n - __old_size); pointer __p = __is_long() ? (__set_long_size(__n), __get_long_pointer()) : (__set_short_size(__n), __get_short_pointer()); traits_type::move(std::__to_address(__p), __s, __n); traits_type::assign(__p[__n], value_type()); if (__old_size > __n) __annotate_shrink(__old_size); return *this; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __null_terminate_at(value_type* __p, size_type __newsz) { size_type __old_size = size(); if (__newsz > __old_size) __annotate_increase(__newsz - __old_size); __set_size(__newsz); traits_type::assign(__p[__newsz], value_type()); if (__old_size > __newsz) __annotate_shrink(__old_size); return *this; } template <class _Tp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __addr_in_range(const _Tp& __v) const { return std::__is_pointer_in_range(data(), data() + size() + 1, std::addressof(__v)); } _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_length_error() const { std::__throw_length_error("basic_string"); } _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("basic_string"); } friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, const basic_string&); friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const value_type*, const basic_string&); friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(value_type, const basic_string&); friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, const value_type*); friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, value_type); }; // These declarations must appear before any functions are implicitly used // so that they have the correct visibility specifier. #define _LIBCPP_DECLARE(...) extern template __VA_ARGS__; #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char) # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t) # endif #else _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char) # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t) # endif #endif #undef _LIBCPP_DECLARE #if _LIBCPP_STD_VER >= 17 template <class _InputIterator, class _CharT = __iter_value_type<_InputIterator>, class _Allocator = allocator<_CharT>, class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Allocator>::value> > basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator()) -> basic_string<_CharT, char_traits<_CharT>, _Allocator>; template <class _CharT, class _Traits, class _Allocator = allocator<_CharT>, class = enable_if_t<__is_allocator<_Allocator>::value> > explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator()) -> basic_string<_CharT, _Traits, _Allocator>; template <class _CharT, class _Traits, class _Allocator = allocator<_CharT>, class = enable_if_t<__is_allocator<_Allocator>::value>, class _Sz = typename allocator_traits<_Allocator>::size_type > basic_string(basic_string_view<_CharT, _Traits>, _Sz, _Sz, const _Allocator& = _Allocator()) -> basic_string<_CharT, _Traits, _Allocator>; #endif #if _LIBCPP_STD_VER >= 23 template <ranges::input_range _Range, class _Allocator = allocator<ranges::range_value_t<_Range>>, class = enable_if_t<__is_allocator<_Allocator>::value> > basic_string(from_range_t, _Range&&, _Allocator = _Allocator()) -> basic_string<ranges::range_value_t<_Range>, char_traits<ranges::range_value_t<_Range>>, _Allocator>; #endif template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz, size_type __reserve) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); if (__reserve > max_size()) __throw_length_error(); pointer __p; if (__fits_in_sso(__reserve)) { __set_short_size(__sz); __p = __get_short_pointer(); } else { auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__reserve) + 1); __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); __set_long_pointer(__p); __set_long_cap(__allocation.count); __set_long_size(__sz); } traits_type::copy(std::__to_address(__p), __s, __sz); traits_type::assign(__p[__sz], value_type()); __annotate_new(__sz); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); if (__sz > max_size()) __throw_length_error(); pointer __p; if (__fits_in_sso(__sz)) { __set_short_size(__sz); __p = __get_short_pointer(); } else { auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1); __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); __set_long_pointer(__p); __set_long_cap(__allocation.count); __set_long_size(__sz); } traits_type::copy(std::__to_address(__p), __s, __sz); traits_type::assign(__p[__sz], value_type()); __annotate_new(__sz); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(const value_type* __s, size_type __sz) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); pointer __p; if (__fits_in_sso(__sz)) { __p = __get_short_pointer(); __set_short_size(__sz); } else { if (__sz > max_size()) __throw_length_error(); auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1); __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); __set_long_pointer(__p); __set_long_cap(__allocation.count); __set_long_size(__sz); } traits_type::copy(std::__to_address(__p), __s, __sz + 1); __annotate_new(__sz); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); if (__n > max_size()) __throw_length_error(); pointer __p; if (__fits_in_sso(__n)) { __set_short_size(__n); __p = __get_short_pointer(); } else { auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__n) + 1); __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); __set_long_pointer(__p); __set_long_cap(__allocation.count); __set_long_size(__n); } traits_type::assign(std::__to_address(__p), __n, __c); traits_type::assign(__p[__n], value_type()); __annotate_new(__n); } template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last) { __init_with_sentinel(std::move(__first), std::move(__last)); } template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator __first, _Sentinel __last) { __r_.first() = __rep(); __annotate_new(0); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __first != __last; ++__first) push_back(*__first); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __annotate_delete(); if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; } #endif // _LIBCPP_HAS_NO_EXCEPTIONS } template <class _CharT, class _Traits, class _Allocator> template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _ForwardIterator __last) { size_type __sz = static_cast<size_type>(std::distance(__first, __last)); __init_with_size(__first, __last, __sz); } template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init_with_size(_InputIterator __first, _Sentinel __last, size_type __sz) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); if (__sz > max_size()) __throw_length_error(); pointer __p; if (__fits_in_sso(__sz)) { __set_short_size(__sz); __p = __get_short_pointer(); } else { auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1); __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); __set_long_pointer(__p); __set_long_cap(__allocation.count); __set_long_size(__sz); } #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __first != __last; ++__first, (void)++__p) traits_type::assign(*__p, *__first); traits_type::assign(*__p, value_type()); #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; } #endif // _LIBCPP_HAS_NO_EXCEPTIONS __annotate_new(__sz); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace( size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add, const value_type* __p_new_stuff) { size_type __ms = max_size(); if (__delta_cap > __ms - __old_cap - 1) __throw_length_error(); pointer __old_p = __get_pointer(); size_type __cap = __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1; __annotate_delete(); auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); if (__n_copy != 0) traits_type::copy(std::__to_address(__p), std::__to_address(__old_p), __n_copy); if (__n_add != 0) traits_type::copy(std::__to_address(__p) + __n_copy, __p_new_stuff, __n_add); size_type __sec_cp_sz = __old_sz - __n_del - __n_copy; if (__sec_cp_sz != 0) traits_type::copy( std::__to_address(__p) + __n_copy + __n_add, std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz); if (__old_cap + 1 != __min_cap) __alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1); __set_long_pointer(__p); __set_long_cap(__allocation.count); __old_sz = __n_copy + __n_add + __sec_cp_sz; __set_long_size(__old_sz); traits_type::assign(__p[__old_sz], value_type()); __annotate_new(__old_cap + __delta_cap); } // __grow_by is deprecated because it does not set the size. It may not update the size when the size is changed, and it // may also not set the size at all when the string was short initially. This leads to unpredictable size value. It is // not removed or changed to avoid breaking the ABI. template <class _CharT, class _Traits, class _Allocator> void _LIBCPP_CONSTEXPR_SINCE_CXX20 #if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1 _LIBCPP_HIDE_FROM_ABI #endif _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Traits, _Allocator>::__grow_by( size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add) { size_type __ms = max_size(); if (__delta_cap > __ms - __old_cap) __throw_length_error(); pointer __old_p = __get_pointer(); size_type __cap = __old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1; __annotate_delete(); auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); if (__n_copy != 0) traits_type::copy(std::__to_address(__p), std::__to_address(__old_p), __n_copy); size_type __sec_cp_sz = __old_sz - __n_del - __n_copy; if (__sec_cp_sz != 0) traits_type::copy( std::__to_address(__p) + __n_copy + __n_add, std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz); if (__old_cap + 1 != __min_cap) __alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1); __set_long_pointer(__p); __set_long_cap(__allocation.count); } template <class _CharT, class _Traits, class _Allocator> void _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace( size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add) { _LIBCPP_SUPPRESS_DEPRECATED_PUSH __grow_by(__old_cap, __delta_cap, __old_sz, __n_copy, __n_del, __n_add); _LIBCPP_SUPPRESS_DEPRECATED_POP __set_long_size(__old_sz - __n_del + __n_add); __annotate_new(__old_sz - __n_del + __n_add); } // assign template <class _CharT, class _Traits, class _Allocator> template <bool __is_short> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* __s, size_type __n) { size_type __cap = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap(); if (__n < __cap) { size_type __old_size = __is_short ? __get_short_size() : __get_long_size(); if (__n > __old_size) __annotate_increase(__n - __old_size); pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer(); __is_short ? __set_short_size(__n) : __set_long_size(__n); traits_type::copy(std::__to_address(__p), __s, __n); traits_type::assign(__p[__n], value_type()); if (__old_size > __n) __annotate_shrink(__old_size); } else { size_type __sz = __is_short ? __get_short_size() : __get_long_size(); __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s); } return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s, size_type __n) { size_type __cap = capacity(); if (__cap >= __n) { size_type __old_size = size(); if (__n > __old_size) __annotate_increase(__n - __old_size); value_type* __p = std::__to_address(__get_pointer()); traits_type::move(__p, __s, __n); return __null_terminate_at(__p, __n); } else { size_type __sz = size(); __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s); return *this; } } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n) { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::assign received nullptr"); return (__builtin_constant_p(__n) && __fits_in_sso(__n)) ? __assign_short(__s, __n) : __assign_external(__s, __n); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c) { size_type __cap = capacity(); size_type __old_size = size(); if (__cap < __n) { size_type __sz = size(); __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); __annotate_increase(__n); } else if (__n > __old_size) __annotate_increase(__n - __old_size); value_type* __p = std::__to_address(__get_pointer()); traits_type::assign(__p, __n, __c); return __null_terminate_at(__p, __n); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { pointer __p; size_type __old_size = size(); if (__old_size == 0) __annotate_increase(1); if (__is_long()) { __p = __get_long_pointer(); __set_long_size(1); } else { __p = __get_short_pointer(); __set_short_size(1); } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); if (__old_size > 1) __annotate_shrink(__old_size); return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) { if (this != std::addressof(__str)) { __copy_assign_alloc(__str); if (!__is_long()) { if (!__str.__is_long()) { size_type __old_size = __get_short_size(); if (__get_short_size() < __str.__get_short_size()) __annotate_increase(__str.__get_short_size() - __get_short_size()); __r_.first() = __str.__r_.first(); if (__old_size > __get_short_size()) __annotate_shrink(__old_size); } else { return __assign_no_alias<true>(__str.data(), __str.size()); } } else { return __assign_no_alias<false>(__str.data(), __str.size()); } } return *this; } #ifndef _LIBCPP_CXX03_LANG template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value) { if (__alloc() != __str.__alloc()) assign(__str); else __move_assign(__str, true_type()); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS void basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type) # if _LIBCPP_STD_VER >= 17 _NOEXCEPT # else _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) # endif { __annotate_delete(); if (__is_long()) { __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); # if _LIBCPP_STD_VER <= 14 if (!is_nothrow_move_assignable<allocator_type>::value) { __set_short_size(0); traits_type::assign(__get_short_pointer()[0], value_type()); __annotate_new(0); } # endif } size_type __str_old_size = __str.size(); bool __str_was_short = !__str.__is_long(); __move_assign_alloc(__str); __r_.first() = __str.__r_.first(); __str.__set_short_size(0); traits_type::assign(__str.__get_short_pointer()[0], value_type()); if (__str_was_short && this != &__str) __str.__annotate_shrink(__str_old_size); else // ASan annotations: was long, so object memory is unpoisoned as new. // Or is same as *this, and __annotate_delete() was called. __str.__annotate_new(0); // ASan annotations: Guard against `std::string s; s = std::move(s);` // You can find more here: https://en.cppreference.com/w/cpp/utility/move // Quote: "Unless otherwise specified, all standard library objects that have been moved // from are placed in a "valid but unspecified state", meaning the object's class // invariants hold (so functions without preconditions, such as the assignment operator, // can be safely used on the object after it was moved from):" // Quote: "v = std::move(v); // the value of v is unspecified" if (!__is_long() && &__str != this) // If it is long string, delete was never called on original __str's buffer. __annotate_new(__get_short_size()); } #endif template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { __assign_with_sentinel(__first, __last); return *this; } template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__assign_with_sentinel(_InputIterator __first, _Sentinel __last) { const basic_string __temp(__init_with_sentinel_tag(), std::move(__first), std::move(__last), __alloc()); assign(__temp.data(), __temp.size()); } template <class _CharT, class _Traits, class _Allocator> template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) { if (__string_is_trivial_iterator<_ForwardIterator>::value) { size_type __n = static_cast<size_type>(std::distance(__first, __last)); __assign_trivial(__first, __last, __n); } else { __assign_with_sentinel(__first, __last); } return *this; } template <class _CharT, class _Traits, class _Allocator> template <class _Iterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _Sentinel __last, size_type __n) { _LIBCPP_ASSERT_INTERNAL( __string_is_trivial_iterator<_Iterator>::value, "The iterator type given to `__assign_trivial` must be trivial"); size_type __old_size = size(); size_type __cap = capacity(); if (__cap < __n) { // Unlike `append` functions, if the input range points into the string itself, there is no case that the input // range could get invalidated by reallocation: // 1. If the input range is a subset of the string itself, its size cannot exceed the capacity of the string, // thus no reallocation would happen. // 2. In the exotic case where the input range is the byte representation of the string itself, the string // object itself stays valid even if reallocation happens. size_type __sz = size(); __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); __annotate_increase(__n); } else if (__n > __old_size) __annotate_increase(__n - __old_size); pointer __p = __get_pointer(); for (; __first != __last; ++__p, (void)++__first) traits_type::assign(*__p, *__first); traits_type::assign(*__p, value_type()); __set_size(__n); if (__n < __old_size) __annotate_shrink(__old_size); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, size_type __pos, size_type __n) { size_type __sz = __str.size(); if (__pos > __sz) __throw_out_of_range(); return assign(__str.data() + __pos, std::min(__n, __sz - __pos)); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp& __t, size_type __pos, size_type __n) { __self_view __sv = __t; size_type __sz = __sv.size(); if (__pos > __sz) __throw_out_of_range(); return assign(__sv.data() + __pos, std::min(__n, __sz - __pos)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) { return __assign_external(__s, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::assign received nullptr"); return __builtin_constant_p(*__s) ? (__fits_in_sso(traits_type::length(__s)) ? __assign_short(__s, traits_type::length(__s)) : __assign_external(__s, traits_type::length(__s))) : __assign_external(__s); } // append template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_type __n) { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::append received nullptr"); size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz >= __n) { if (__n) { __annotate_increase(__n); value_type* __p = std::__to_address(__get_pointer()); traits_type::copy(__p + __sz, __s, __n); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } } else __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __sz, 0, __n, __s); return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c) { if (__n) { size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz < __n) __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); __annotate_increase(__n); pointer __p = __get_pointer(); traits_type::assign(std::__to_address(__p) + __sz, __n, __c); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 inline void basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n) { if (__n) { size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz < __n) __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); __annotate_increase(__n); pointer __p = __get_pointer(); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c) { bool __is_short = !__is_long(); size_type __cap; size_type __sz; if (__is_short) { __cap = __min_cap - 1; __sz = __get_short_size(); } else { __cap = __get_long_cap() - 1; __sz = __get_long_size(); } if (__sz == __cap) { __grow_by_without_replace(__cap, 1, __sz, __sz, 0); __annotate_increase(1); __is_short = false; // the string is always long after __grow_by } else __annotate_increase(1); pointer __p = __get_pointer(); if (__is_short) { __p = __get_short_pointer() + __sz; __set_short_size(__sz + 1); } else { __p = __get_long_pointer() + __sz; __set_long_size(__sz + 1); } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); } template <class _CharT, class _Traits, class _Allocator> template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(_ForwardIterator __first, _ForwardIterator __last) { size_type __sz = size(); size_type __cap = capacity(); size_type __n = static_cast<size_type>(std::distance(__first, __last)); if (__n) { if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first)) { if (__cap - __sz < __n) __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); __annotate_increase(__n); pointer __p = __get_pointer() + __sz; for (; __first != __last; ++__p, (void)++__first) traits_type::assign(*__p, *__first); traits_type::assign(*__p, value_type()); __set_size(__sz + __n); } else { const basic_string __temp(__first, __last, __alloc()); append(__temp.data(), __temp.size()); } } return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, size_type __pos, size_type __n) { size_type __sz = __str.size(); if (__pos > __sz) __throw_out_of_range(); return append(__str.data() + __pos, std::min(__n, __sz - __pos)); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const _Tp& __t, size_type __pos, size_type __n) { __self_view __sv = __t; size_type __sz = __sv.size(); if (__pos > __sz) __throw_out_of_range(); return append(__sv.data() + __pos, std::min(__n, __sz - __pos)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::append received nullptr"); return append(__s, traits_type::length(__s)); } // insert template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s, size_type __n) { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::insert received nullptr"); size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); size_type __cap = capacity(); if (__cap - __sz >= __n) { if (__n) { __annotate_increase(__n); value_type* __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) { if (std::__is_pointer_in_range(__p + __pos, __p + __sz, __s)) __s += __n; traits_type::move(__p + __pos + __n, __p + __pos, __n_move); } traits_type::move(__p + __pos, __s, __n); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } } else __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n, __s); return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n, value_type __c) { size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); if (__n) { size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { __annotate_increase(__n); __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) traits_type::move(__p + __pos + __n, __p + __pos, __n_move); } else { __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n); __p = std::__to_address(__get_long_pointer()); } traits_type::assign(__p + __pos, __n, __c); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } return *this; } template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) { const basic_string __temp(__first, __last, __alloc()); return insert(__pos, __temp.data(), __temp.data() + __temp.size()); } template <class _CharT, class _Traits, class _Allocator> template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert( const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) { auto __n = static_cast<size_type>(std::distance(__first, __last)); return __insert_with_size(__pos, __first, __last, __n); } template <class _CharT, class _Traits, class _Allocator> template <class _Iterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::__insert_with_size( const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n) { size_type __ip = static_cast<size_type>(__pos - begin()); if (__n == 0) return begin() + __ip; if (__string_is_trivial_iterator<_Iterator>::value && !__addr_in_range(*__first)) { return __insert_from_safe_copy(__n, __ip, __first, __last); } else { const basic_string __temp(__init_with_sentinel_tag(), __first, __last, __alloc()); return __insert_from_safe_copy(__n, __ip, __temp.begin(), __temp.end()); } } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert( size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n) { size_type __str_sz = __str.size(); if (__pos2 > __str_sz) __throw_out_of_range(); return insert(__pos1, __str.data() + __pos2, std::min(__n, __str_sz - __pos2)); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n) { __self_view __sv = __t; size_type __str_sz = __sv.size(); if (__pos2 > __str_sz) __throw_out_of_range(); return insert(__pos1, __sv.data() + __pos2, std::min(__n, __str_sz - __pos2)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::insert received nullptr"); return insert(__pos, __s, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_type __c) { size_type __ip = static_cast<size_type>(__pos - begin()); size_type __sz = size(); size_type __cap = capacity(); value_type* __p; if (__cap == __sz) { __grow_by_without_replace(__cap, 1, __sz, __ip, 0, 1); __p = std::__to_address(__get_long_pointer()); } else { __annotate_increase(1); __p = std::__to_address(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) traits_type::move(__p + __ip + 1, __p + __ip, __n_move); } traits_type::assign(__p[__ip], __c); traits_type::assign(__p[++__sz], value_type()); __set_size(__sz); return begin() + static_cast<difference_type>(__ip); } // replace template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace( size_type __pos, size_type __n1, const value_type* __s, size_type __n2) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { _LIBCPP_ASSERT_NON_NULL(__n2 == 0 || __s != nullptr, "string::replace received nullptr"); size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); __n1 = std::min(__n1, __sz - __pos); size_type __cap = capacity(); if (__cap - __sz + __n1 >= __n2) { value_type* __p = std::__to_address(__get_pointer()); if (__n1 != __n2) { if (__n2 > __n1) __annotate_increase(__n2 - __n1); size_type __n_move = __sz - __pos - __n1; if (__n_move != 0) { if (__n1 > __n2) { traits_type::move(__p + __pos, __s, __n2); traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); return __null_terminate_at(__p, __sz + (__n2 - __n1)); } if (std::__is_pointer_in_range(__p + __pos + 1, __p + __sz, __s)) { if (__p + __pos + __n1 <= __s) __s += __n2 - __n1; else // __p + __pos < __s < __p + __pos + __n1 { traits_type::move(__p + __pos, __s, __n1); __pos += __n1; __s += __n2; __n2 -= __n1; __n1 = 0; } } traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); } } traits_type::move(__p + __pos, __s, __n2); return __null_terminate_at(__p, __sz + (__n2 - __n1)); } else __grow_by_and_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2, __s); return *this; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, size_type __n2, value_type __c) { size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); __n1 = std::min(__n1, __sz - __pos); size_type __cap = capacity(); value_type* __p; if (__cap - __sz + __n1 >= __n2) { __p = std::__to_address(__get_pointer()); if (__n1 != __n2) { if (__n2 > __n1) __annotate_increase(__n2 - __n1); size_type __n_move = __sz - __pos - __n1; if (__n_move != 0) traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); } } else { __grow_by_without_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2); __p = std::__to_address(__get_long_pointer()); } traits_type::assign(__p + __pos, __n2, __c); return __null_terminate_at(__p, __sz - (__n1 - __n2)); } template <class _CharT, class _Traits, class _Allocator> template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace( const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2) { const basic_string __temp(__j1, __j2, __alloc()); return replace(__i1, __i2, __temp); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace( size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2) { size_type __str_sz = __str.size(); if (__pos2 > __str_sz) __throw_out_of_range(); return replace(__pos1, __n1, __str.data() + __pos2, std::min(__n2, __str_sz - __pos2)); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace( size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) { __self_view __sv = __t; size_type __str_sz = __sv.size(); if (__pos2 > __str_sz) __throw_out_of_range(); return replace(__pos1, __n1, __sv.data() + __pos2, std::min(__n2, __str_sz - __pos2)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s) { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::replace received nullptr"); return replace(__pos, __n1, __s, traits_type::length(__s)); } // erase // 'externally instantiated' erase() implementation, called when __n != npos. // Does not check __pos against size() template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void basic_string<_CharT, _Traits, _Allocator>::__erase_external_with_move(size_type __pos, size_type __n) { if (__n) { size_type __sz = size(); value_type* __p = std::__to_address(__get_pointer()); __n = std::min(__n, __sz - __pos); size_type __n_move = __sz - __pos - __n; if (__n_move != 0) traits_type::move(__p + __pos, __p + __pos + __n, __n_move); __null_terminate_at(__p, __sz - __n); } } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, size_type __n) { if (__pos > size()) __throw_out_of_range(); if (__n == npos) { __erase_to_end(__pos); } else { __erase_external_with_move(__pos, __n); } return *this; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __pos != end(), "string::erase(iterator) called with a non-dereferenceable iterator"); iterator __b = begin(); size_type __r = static_cast<size_type>(__pos - __b); erase(__r, 1); return __b + static_cast<difference_type>(__r); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last) { _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "string::erase(first, last) called with invalid range"); iterator __b = begin(); size_type __r = static_cast<size_type>(__first - __b); erase(__r, static_cast<size_type>(__last - __first)); return __b + static_cast<difference_type>(__r); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pop_back() { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty"); __erase_to_end(size() - 1); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT { size_type __old_size = size(); if (__is_long()) { traits_type::assign(*__get_long_pointer(), value_type()); __set_long_size(0); } else { traits_type::assign(*__get_short_pointer(), value_type()); __set_short_size(0); } __annotate_shrink(__old_size); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::resize(size_type __n, value_type __c) { size_type __sz = size(); if (__n > __sz) append(__n - __sz, __c); else __erase_to_end(__n); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 inline void basic_string<_CharT, _Traits, _Allocator>::__resize_default_init(size_type __n) { size_type __sz = size(); if (__n > __sz) { __append_default_init(__n - __sz); } else __erase_to_end(__n); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::reserve(size_type __requested_capacity) { if (__requested_capacity > max_size()) __throw_length_error(); // Make sure reserve(n) never shrinks. This is technically only required in C++20 // and later (since P0966R1), however we provide consistent behavior in all Standard // modes because this function is instantiated in the shared library. if (__requested_capacity <= capacity()) return; size_type __target_capacity = std::max(__requested_capacity, size()); __target_capacity = __recommend(__target_capacity); if (__target_capacity == capacity()) return; __shrink_or_extend(__target_capacity); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::shrink_to_fit() _NOEXCEPT { size_type __target_capacity = __recommend(size()); if (__target_capacity == capacity()) return; __shrink_or_extend(__target_capacity); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity) { __annotate_delete(); size_type __cap = capacity(); size_type __sz = size(); pointer __new_data, __p; bool __was_long, __now_long; if (__fits_in_sso(__target_capacity)) { __was_long = true; __now_long = false; __new_data = __get_short_pointer(); __p = __get_long_pointer(); } else { if (__target_capacity > __cap) { auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1); __new_data = __allocation.ptr; __target_capacity = __allocation.count - 1; } else { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif // _LIBCPP_HAS_NO_EXCEPTIONS auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1); __new_data = __allocation.ptr; __target_capacity = __allocation.count - 1; #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { return; } #else // _LIBCPP_HAS_NO_EXCEPTIONS if (__new_data == nullptr) return; #endif // _LIBCPP_HAS_NO_EXCEPTIONS } __begin_lifetime(__new_data, __target_capacity + 1); __now_long = true; __was_long = __is_long(); __p = __get_pointer(); } traits_type::copy(std::__to_address(__new_data), std::__to_address(__p), size() + 1); if (__was_long) __alloc_traits::deallocate(__alloc(), __p, __cap + 1); if (__now_long) { __set_long_cap(__target_capacity + 1); __set_long_size(__sz); __set_long_pointer(__new_data); } else __set_short_size(__sz); __annotate_new(__sz); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const { if (__n >= size()) __throw_out_of_range(); return (*this)[__n]; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) { if (__n >= size()) __throw_out_of_range(); return (*this)[__n]; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::copy(value_type* __s, size_type __n, size_type __pos) const { size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); size_type __rlen = std::min(__n, __sz - __pos); traits_type::copy(__s, data() + __pos, __rlen); return __rlen; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<allocator_type>::value) #endif { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value || __alloc() == __str.__alloc(), "swapping non-equal allocators"); if (!__is_long()) __annotate_delete(); if (this != &__str && !__str.__is_long()) __str.__annotate_delete(); std::swap(__r_.first(), __str.__r_.first()); std::__swap_allocator(__alloc(), __str.__alloc()); if (!__is_long()) __annotate_new(__get_short_size()); if (this != &__str && !__str.__is_long()) __str.__annotate_new(__str.__get_short_size()); } // find template <class _Traits> struct _LIBCPP_HIDDEN __traits_eq { typedef typename _Traits::char_type char_type; _LIBCPP_HIDE_FROM_ABI bool operator()(const char_type& __x, const char_type& __y) _NOEXCEPT { return _Traits::eq(__x, __y); } }; template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find(): received nullptr"); return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __str.data(), __pos, __str.size()); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __sv.data(), __pos, __sv.size()); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find(): received nullptr"); return std::__str_find<value_type, size_type, traits_type, npos>( data(), size(), __s, __pos, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(value_type __c, size_type __pos) const _NOEXCEPT { return std::__str_find<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos); } // rfind template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind( const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::rfind(): received nullptr"); return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __str.data(), __pos, __str.size()); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __sv.data(), __pos, __sv.size()); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::rfind(): received nullptr"); return std::__str_rfind<value_type, size_type, traits_type, npos>( data(), size(), __s, __pos, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(value_type __c, size_type __pos) const _NOEXCEPT { return std::__str_rfind<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos); } // find_first_of template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of( const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr"); return std::__str_find_first_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_find_first_of<value_type, size_type, traits_type, npos>( data(), size(), __str.data(), __pos, __str.size()); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_first_of<value_type, size_type, traits_type, npos>( data(), size(), __sv.data(), __pos, __sv.size()); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_first_of(): received nullptr"); return std::__str_find_first_of<value_type, size_type, traits_type, npos>( data(), size(), __s, __pos, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(value_type __c, size_type __pos) const _NOEXCEPT { return find(__c, __pos); } // find_last_of template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of( const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr"); return std::__str_find_last_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_find_last_of<value_type, size_type, traits_type, npos>( data(), size(), __str.data(), __pos, __str.size()); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_last_of<value_type, size_type, traits_type, npos>( data(), size(), __sv.data(), __pos, __sv.size()); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_last_of(): received nullptr"); return std::__str_find_last_of<value_type, size_type, traits_type, npos>( data(), size(), __s, __pos, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(value_type __c, size_type __pos) const _NOEXCEPT { return rfind(__c, __pos); } // find_first_not_of template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of( const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of( const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>( data(), size(), __str.data(), __pos, __str.size()); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>( data(), size(), __sv.data(), __pos, __sv.size()); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>( data(), size(), __s, __pos, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c, size_type __pos) const _NOEXCEPT { return std::__str_find_first_not_of<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos); } // find_last_not_of template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of( const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>(data(), size(), __s, __pos, __n); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of( const basic_string& __str, size_type __pos) const _NOEXCEPT { return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>( data(), size(), __str.data(), __pos, __str.size()); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>( data(), size(), __sv.data(), __pos, __sv.size()); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>( data(), size(), __s, __pos, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c, size_type __pos) const _NOEXCEPT { return std::__str_find_last_not_of<value_type, size_type, traits_type, npos>(data(), size(), __c, __pos); } // compare template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const _NOEXCEPT { __self_view __sv = __t; size_t __lhs_sz = size(); size_t __rhs_sz = __sv.size(); int __result = traits_type::compare(data(), __sv.data(), std::min(__lhs_sz, __rhs_sz)); if (__result != 0) return __result; if (__lhs_sz < __rhs_sz) return -1; if (__lhs_sz > __rhs_sz) return 1; return 0; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const basic_string& __str) const _NOEXCEPT { return compare(__self_view(__str)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare( size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const { _LIBCPP_ASSERT_NON_NULL(__n2 == 0 || __s != nullptr, "string::compare(): received nullptr"); size_type __sz = size(); if (__pos1 > __sz || __n2 == npos) __throw_out_of_range(); size_type __rlen = std::min(__n1, __sz - __pos1); int __r = traits_type::compare(data() + __pos1, __s, std::min(__rlen, __n2)); if (__r == 0) { if (__rlen < __n2) __r = -1; else if (__rlen > __n2) __r = 1; } return __r; } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const _Tp& __t) const { __self_view __sv = __t; return compare(__pos1, __n1, __sv.data(), __sv.size()); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const basic_string& __str) const { return compare(__pos1, __n1, __str.data(), __str.size()); } template <class _CharT, class _Traits, class _Allocator> template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare( size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) const { __self_view __sv = __t; return __self_view(*this).substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare( size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2) const { return compare(__pos1, __n1, __self_view(__str), __pos2, __n2); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const value_type* __s) const _NOEXCEPT { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::compare(): received nullptr"); return compare(0, npos, __s, traits_type::length(__s)); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const value_type* __s) const { _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::compare(): received nullptr"); return compare(__pos1, __n1, __s, traits_type::length(__s)); } // __invariants template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 bool basic_string<_CharT, _Traits, _Allocator>::__invariants() const { if (size() > capacity()) return false; if (capacity() < __min_cap - 1) return false; if (data() == nullptr) return false; if (!_Traits::eq(data()[size()], value_type())) return false; return true; } // __clear_and_shrink template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() _NOEXCEPT { clear(); if (__is_long()) { __annotate_delete(); __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1); __r_.first() = __rep(); } } // operator== template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { #if _LIBCPP_STD_VER >= 20 return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs); #else size_t __lhs_sz = __lhs.size(); return __lhs_sz == __rhs.size() && _Traits::compare(__lhs.data(), __rhs.data(), __lhs_sz) == 0; #endif } template <class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool operator==(const basic_string<char, char_traits<char>, _Allocator>& __lhs, const basic_string<char, char_traits<char>, _Allocator>& __rhs) _NOEXCEPT { size_t __lhs_sz = __lhs.size(); if (__lhs_sz != __rhs.size()) return false; const char* __lp = __lhs.data(); const char* __rp = __rhs.data(); if (__lhs.__is_long()) return char_traits<char>::compare(__lp, __rp, __lhs_sz) == 0; for (; __lhs_sz != 0; --__lhs_sz, ++__lp, ++__rp) if (*__lp != *__rp) return false; return true; } #if _LIBCPP_STD_VER <= 17 template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator==(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { typedef basic_string<_CharT, _Traits, _Allocator> _String; _LIBCPP_ASSERT_NON_NULL(__lhs != nullptr, "operator==(char*, basic_string): received nullptr"); size_t __lhs_len = _Traits::length(__lhs); if (__lhs_len != __rhs.size()) return false; return __rhs.compare(0, _String::npos, __lhs, __lhs_len) == 0; } #endif // _LIBCPP_STD_VER <= 17 template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { #if _LIBCPP_STD_VER >= 20 return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs); #else typedef basic_string<_CharT, _Traits, _Allocator> _String; _LIBCPP_ASSERT_NON_NULL(__rhs != nullptr, "operator==(basic_string, char*): received nullptr"); size_t __rhs_len = _Traits::length(__rhs); if (__rhs_len != __lhs.size()) return false; return __lhs.compare(0, _String::npos, __rhs, __rhs_len) == 0; #endif } #if _LIBCPP_STD_VER >= 20 template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) noexcept { return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs); } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs); } #else // _LIBCPP_STD_VER >= 20 template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs == __rhs); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs == __rhs); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return !(__lhs == __rhs); } // operator< template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator<(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __lhs.compare(__rhs) < 0; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator<(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return __lhs.compare(__rhs) < 0; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator<(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __rhs.compare(__lhs) > 0; } // operator> template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __rhs < __lhs; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return __rhs < __lhs; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator>(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __rhs < __lhs; } // operator<= template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__rhs < __lhs); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return !(__rhs < __lhs); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__rhs < __lhs); } // operator>= template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs < __rhs); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return !(__lhs < __rhs); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs < __rhs); } #endif // _LIBCPP_STD_VER >= 20 // operator + template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { using _String = basic_string<_CharT, _Traits, _Allocator>; auto __lhs_sz = __lhs.size(); auto __rhs_sz = __rhs.size(); _String __r(__uninitialized_size_tag(), __lhs_sz + __rhs_sz, _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator())); auto __ptr = std::__to_address(__r.__get_pointer()); _Traits::copy(__ptr, __lhs.data(), __lhs_sz); _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz); _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT()); return __r; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { using _String = basic_string<_CharT, _Traits, _Allocator>; auto __lhs_sz = _Traits::length(__lhs); auto __rhs_sz = __rhs.size(); _String __r(__uninitialized_size_tag(), __lhs_sz + __rhs_sz, _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator())); auto __ptr = std::__to_address(__r.__get_pointer()); _Traits::copy(__ptr, __lhs, __lhs_sz); _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz); _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT()); return __r; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { using _String = basic_string<_CharT, _Traits, _Allocator>; typename _String::size_type __rhs_sz = __rhs.size(); _String __r(__uninitialized_size_tag(), __rhs_sz + 1, _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator())); auto __ptr = std::__to_address(__r.__get_pointer()); _Traits::assign(__ptr, 1, __lhs); _Traits::copy(__ptr + 1, __rhs.data(), __rhs_sz); _Traits::assign(__ptr + 1 + __rhs_sz, 1, _CharT()); return __r; } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { using _String = basic_string<_CharT, _Traits, _Allocator>; typename _String::size_type __lhs_sz = __lhs.size(); typename _String::size_type __rhs_sz = _Traits::length(__rhs); _String __r(__uninitialized_size_tag(), __lhs_sz + __rhs_sz, _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator())); auto __ptr = std::__to_address(__r.__get_pointer()); _Traits::copy(__ptr, __lhs.data(), __lhs_sz); _Traits::copy(__ptr + __lhs_sz, __rhs, __rhs_sz); _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT()); return __r; } template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, _CharT __rhs) { using _String = basic_string<_CharT, _Traits, _Allocator>; typename _String::size_type __lhs_sz = __lhs.size(); _String __r(__uninitialized_size_tag(), __lhs_sz + 1, _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator())); auto __ptr = std::__to_address(__r.__get_pointer()); _Traits::copy(__ptr, __lhs.data(), __lhs_sz); _Traits::assign(__ptr + __lhs_sz, 1, __rhs); _Traits::assign(__ptr + 1 + __lhs_sz, 1, _CharT()); return __r; } #ifndef _LIBCPP_CXX03_LANG template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { return std::move(__lhs.append(__rhs)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { return std::move(__rhs.insert(0, __lhs)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { return std::move(__lhs.append(__rhs)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const _CharT* __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { return std::move(__rhs.insert(0, __lhs)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(_CharT __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { __rhs.insert(__rhs.begin(), __lhs); return std::move(__rhs); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const _CharT* __rhs) { return std::move(__lhs.append(__rhs)); } template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, _CharT __rhs) { __lhs.push_back(__rhs); return std::move(__lhs); } #endif // _LIBCPP_CXX03_LANG // swap template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT_(_NOEXCEPT_(__lhs.swap(__rhs))) { __lhs.swap(__rhs); } _LIBCPP_EXPORTED_FROM_ABI int stoi(const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI long stol(const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI unsigned long stoul(const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI long long stoll(const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI unsigned long long stoull(const string& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI float stof(const string& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI double stod(const string& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI long double stold(const string& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI string to_string(int __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(long __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned long __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(long long __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned long long __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(float __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(double __val); _LIBCPP_EXPORTED_FROM_ABI string to_string(long double __val); #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS _LIBCPP_EXPORTED_FROM_ABI int stoi(const wstring& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI long stol(const wstring& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI unsigned long stoul(const wstring& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI long long stoll(const wstring& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI unsigned long long stoull(const wstring& __str, size_t* __idx = nullptr, int __base = 10); _LIBCPP_EXPORTED_FROM_ABI float stof(const wstring& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI double stod(const wstring& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI long double stold(const wstring& __str, size_t* __idx = nullptr); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(int __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned long __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long long __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned long long __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(float __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(double __val); _LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long double __val); #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class _CharT, class _Traits, class _Allocator> _LIBCPP_TEMPLATE_DATA_VIS const typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::npos; template <class _CharT, class _Allocator> struct __string_hash : public __unary_function<basic_string<_CharT, char_traits<_CharT>, _Allocator>, size_t> { _LIBCPP_HIDE_FROM_ABI size_t operator()(const basic_string<_CharT, char_traits<_CharT>, _Allocator>& __val) const _NOEXCEPT { return std::__do_string_hash(__val.data(), __val.data() + __val.size()); } }; template <class _Allocator> struct hash<basic_string<char, char_traits<char>, _Allocator> > : __string_hash<char, _Allocator> {}; #ifndef _LIBCPP_HAS_NO_CHAR8_T template <class _Allocator> struct hash<basic_string<char8_t, char_traits<char8_t>, _Allocator> > : __string_hash<char8_t, _Allocator> {}; #endif template <class _Allocator> struct hash<basic_string<char16_t, char_traits<char16_t>, _Allocator> > : __string_hash<char16_t, _Allocator> {}; template <class _Allocator> struct hash<basic_string<char32_t, char_traits<char32_t>, _Allocator> > : __string_hash<char32_t, _Allocator> {}; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class _Allocator> struct hash<basic_string<wchar_t, char_traits<wchar_t>, _Allocator> > : __string_hash<wchar_t, _Allocator> {}; #endif template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const basic_string<_CharT, _Traits, _Allocator>& __str); template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& operator>>(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str); template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm); template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str); template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm); template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str); #if _LIBCPP_STD_VER >= 20 template <class _CharT, class _Traits, class _Allocator, class _Up> inline _LIBCPP_HIDE_FROM_ABI typename basic_string<_CharT, _Traits, _Allocator>::size_type erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) { auto __old_size = __str.size(); __str.erase(std::remove(__str.begin(), __str.end(), __v), __str.end()); return __old_size - __str.size(); } template <class _CharT, class _Traits, class _Allocator, class _Predicate> inline _LIBCPP_HIDE_FROM_ABI typename basic_string<_CharT, _Traits, _Allocator>::size_type erase_if(basic_string<_CharT, _Traits, _Allocator>& __str, _Predicate __pred) { auto __old_size = __str.size(); __str.erase(std::remove_if(__str.begin(), __str.end(), __pred), __str.end()); return __old_size - __str.size(); } #endif #if _LIBCPP_STD_VER >= 14 // Literal suffixes for basic_string [basic.string.literals] inline namespace literals { inline namespace string_literals { inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char> operator""s(const char* __str, size_t __len) { return basic_string<char>(__str, __len); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<wchar_t> operator""s(const wchar_t* __str, size_t __len) { return basic_string<wchar_t>(__str, __len); } # endif # ifndef _LIBCPP_HAS_NO_CHAR8_T inline _LIBCPP_HIDE_FROM_ABI constexpr basic_string<char8_t> operator""s(const char8_t* __str, size_t __len) { return basic_string<char8_t>(__str, __len); } # endif inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char16_t> operator""s(const char16_t* __str, size_t __len) { return basic_string<char16_t>(__str, __len); } inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<char32_t> operator""s(const char32_t* __str, size_t __len) { return basic_string<char32_t>(__str, __len); } } // namespace string_literals } // namespace literals # if _LIBCPP_STD_VER >= 20 template <> inline constexpr bool __format::__enable_insertable<std::basic_string<char>> = true; # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> inline constexpr bool __format::__enable_insertable<std::basic_string<wchar_t>> = true; # endif # endif #endif _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <algorithm> # include <concepts> # include <cstdlib> # include <iterator> # include <new> # include <type_traits> # include <typeinfo> # include <utility> #endif #endif // _LIBCPP_STRING #endif // _LIBCPP_NEW_STRING #ifdef _LIBCPP_OLD_STRING char *bar() { return new char[32]{"_LIBCPP_OLD_STRING"}; } #endif #ifdef _LIBCPP_NEW_STRING char *bar() { return new char[32]{"_LIBCPP_NEW_STRING"};} #endif std::string foo(std::string& s) { std::string s2(std::move(s)); if(s2 == "x") { return s; } else { return s2; } }
Become a Patron
Sponsor on GitHub
Donate via PayPal
Source on GitHub
Mailing list
Installed libraries
Wiki
Report an issue
How it works
Contact the author
CE on Mastodon
CE on Bluesky
About the author
Statistics
Changelog
Version tree