Thanks for using Compiler Explorer
Sponsors
Jakt
C++
Ada
Algol68
Analysis
Android Java
Android Kotlin
Assembly
C
C3
Carbon
C with Coccinelle
C++ with Coccinelle
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
Mojo
Nim
Numba
Nix
Objective-C
Objective-C++
OCaml
Odin
OpenCL C
Pascal
Pony
PTX
Python
Racket
Raku
Ruby
Rust
Sail
Snowball
Scala
Slang
Solidity
Spice
SPIR-V
Swift
LLVM TableGen
Toit
Triton
TypeScript Native
V
Vala
Visual Basic
Vyper
WASM
Zig
Javascript
GIMPLE
Ygen
sway
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 12.5.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 13.4.0
ARM GCC 13.4.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 14.3.0
ARM GCC 14.3.0 (unknown-eabi)
ARM GCC 15.1.0
ARM GCC 15.1.0 (unknown-eabi)
ARM GCC 15.2.0
ARM GCC 15.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 (ex-WINE)
ARM msvc v19.10 (ex-WINE)
ARM msvc v19.14 (ex-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 12.5.0
ARM64 gcc 13.1.0
ARM64 gcc 13.2.0
ARM64 gcc 13.3.0
ARM64 gcc 13.4.0
ARM64 gcc 14.1.0
ARM64 gcc 14.2.0
ARM64 gcc 14.3.0
ARM64 gcc 15.1.0
ARM64 gcc 15.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 (ex-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 12.5.0
AVR gcc 13.1.0
AVR gcc 13.2.0
AVR gcc 13.3.0
AVR gcc 13.4.0
AVR gcc 14.1.0
AVR gcc 14.2.0
AVR gcc 14.3.0
AVR gcc 15.1.0
AVR gcc 15.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
BPF clang 20.1.0
BPF clang 21.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)
EDG 6.7
EDG 6.7 (GNU mode gcc 14)
FRC 2019
FRC 2020
FRC 2023
HPPA gcc 14.2.0
HPPA gcc 14.3.0
HPPA gcc 15.1.0
HPPA gcc 15.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
LoongArch64 clang 20.1.0
LoongArch64 clang 21.1.0
M68K gcc 13.1.0
M68K gcc 13.2.0
M68K gcc 13.3.0
M68K gcc 13.4.0
M68K gcc 14.1.0
M68K gcc 14.2.0
M68K gcc 14.3.0
M68K gcc 15.1.0
M68K gcc 15.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
MinGW gcc 14.3.0
MinGW gcc 15.2.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 12.5.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 13.4.0
RISC-V (32-bits) gcc 14.1.0
RISC-V (32-bits) gcc 14.2.0
RISC-V (32-bits) gcc 14.3.0
RISC-V (32-bits) gcc 15.1.0
RISC-V (32-bits) gcc 15.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 12.5.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 13.4.0
RISC-V (64-bits) gcc 14.1.0
RISC-V (64-bits) gcc 14.2.0
RISC-V (64-bits) gcc 14.3.0
RISC-V (64-bits) gcc 15.1.0
RISC-V (64-bits) gcc 15.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 20.1.0
RISC-V rv32gc clang 21.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 20.1.0
RISC-V rv64gc clang 21.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 12.5.0
SPARC LEON gcc 13.1.0
SPARC LEON gcc 13.2.0
SPARC LEON gcc 13.3.0
SPARC LEON gcc 13.4.0
SPARC LEON gcc 14.1.0
SPARC LEON gcc 14.2.0
SPARC LEON gcc 14.3.0
SPARC LEON gcc 15.1.0
SPARC LEON gcc 15.2.0
SPARC gcc 12.2.0
SPARC gcc 12.3.0
SPARC gcc 12.4.0
SPARC gcc 12.5.0
SPARC gcc 13.1.0
SPARC gcc 13.2.0
SPARC gcc 13.3.0
SPARC gcc 13.4.0
SPARC gcc 14.1.0
SPARC gcc 14.2.0
SPARC gcc 14.3.0
SPARC gcc 15.1.0
SPARC gcc 15.2.0
SPARC64 gcc 12.2.0
SPARC64 gcc 12.3.0
SPARC64 gcc 12.4.0
SPARC64 gcc 12.5.0
SPARC64 gcc 13.1.0
SPARC64 gcc 13.2.0
SPARC64 gcc 13.3.0
SPARC64 gcc 13.4.0
SPARC64 gcc 14.1.0
SPARC64 gcc 14.2.0
SPARC64 gcc 14.3.0
SPARC64 gcc 15.1.0
SPARC64 gcc 15.2.0
TI C6x gcc 12.2.0
TI C6x gcc 12.3.0
TI C6x gcc 12.4.0
TI C6x gcc 12.5.0
TI C6x gcc 13.1.0
TI C6x gcc 13.2.0
TI C6x gcc 13.3.0
TI C6x gcc 13.4.0
TI C6x gcc 14.1.0
TI C6x gcc 14.2.0
TI C6x gcc 14.3.0
TI C6x gcc 15.1.0
TI C6x gcc 15.2.0
TI CL430 21.6.1
Tricore gcc 11.3.0 (EEESlab)
VAX gcc NetBSDELF 10.4.0
VAX gcc NetBSDELF 10.5.0 (Nov 15 03:50:22 2023)
VAX gcc NetBSDELF 12.4.0 (Apr 16 05:27 2025)
WebAssembly clang (trunk)
Xtensa ESP32 gcc 11.2.0 (2022r1)
Xtensa ESP32 gcc 12.2.0 (20230208)
Xtensa ESP32 gcc 14.2.0 (20241119)
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 14.2.0 (20241119)
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 14.2.0 (20241119)
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.41 VS17.11
arm64 msvc v19.42 VS17.12
arm64 msvc v19.43 VS17.13
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 20.1.0
armv7-a clang 21.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 20.1.0
armv8-a clang 21.1.0
armv8-a clang 9.0.0
armv8-a clang 9.0.1
clad trunk (clang 21.1.0)
clad v1.10 (clang 20.1.0)
clad v1.8 (clang 18.1.0)
clad v1.9 (clang 19.1.0)
clad v2.00 (clang 20.1.0)
clang-cl 18.1.0
ellcc 0.1.33
ellcc 0.1.34
ellcc 2017-07-16
ez80-clang 15.0.0
ez80-clang 15.0.7
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 12.5.0
loongarch64 gcc 13.1.0
loongarch64 gcc 13.2.0
loongarch64 gcc 13.3.0
loongarch64 gcc 13.4.0
loongarch64 gcc 14.1.0
loongarch64 gcc 14.2.0
loongarch64 gcc 14.3.0
loongarch64 gcc 15.1.0
loongarch64 gcc 15.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 clang 20.1.0
mips clang 21.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 12.5.0
mips gcc 13.1.0
mips gcc 13.2.0
mips gcc 13.3.0
mips gcc 13.4.0
mips gcc 14.1.0
mips gcc 14.2.0
mips gcc 14.3.0
mips gcc 15.1.0
mips gcc 15.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 12.5.0
mips64 (el) gcc 13.1.0
mips64 (el) gcc 13.2.0
mips64 (el) gcc 13.3.0
mips64 (el) gcc 13.4.0
mips64 (el) gcc 14.1.0
mips64 (el) gcc 14.2.0
mips64 (el) gcc 14.3.0
mips64 (el) gcc 15.1.0
mips64 (el) gcc 15.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 clang 20.1.0
mips64 clang 21.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 12.5.0
mips64 gcc 13.1.0
mips64 gcc 13.2.0
mips64 gcc 13.3.0
mips64 gcc 13.4.0
mips64 gcc 14.1.0
mips64 gcc 14.2.0
mips64 gcc 14.3.0
mips64 gcc 15.1.0
mips64 gcc 15.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
mips64el clang 20.1.0
mips64el clang 21.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 clang 20.1.0
mipsel clang 21.1.0
mipsel gcc 12.1.0
mipsel gcc 12.2.0
mipsel gcc 12.3.0
mipsel gcc 12.4.0
mipsel gcc 12.5.0
mipsel gcc 13.1.0
mipsel gcc 13.2.0
mipsel gcc 13.3.0
mipsel gcc 13.4.0
mipsel gcc 14.1.0
mipsel gcc 14.2.0
mipsel gcc 14.3.0
mipsel gcc 15.1.0
mipsel gcc 15.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 12.5.0
power gcc 13.1.0
power gcc 13.2.0
power gcc 13.3.0
power gcc 13.4.0
power gcc 14.1.0
power gcc 14.2.0
power gcc 14.3.0
power gcc 15.1.0
power gcc 15.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 12.5.0
power64 gcc 13.1.0
power64 gcc 13.2.0
power64 gcc 13.3.0
power64 gcc 13.4.0
power64 gcc 14.1.0
power64 gcc 14.2.0
power64 gcc 14.3.0
power64 gcc 15.1.0
power64 gcc 15.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 12.5.0
power64le gcc 13.1.0
power64le gcc 13.2.0
power64le gcc 13.3.0
power64le gcc 13.4.0
power64le gcc 14.1.0
power64le gcc 14.2.0
power64le gcc 14.3.0
power64le gcc 15.1.0
power64le gcc 15.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 12.5.0
s390x gcc 13.1.0
s390x gcc 13.2.0
s390x gcc 13.3.0
s390x gcc 13.4.0
s390x gcc 14.1.0
s390x gcc 14.2.0
s390x gcc 14.3.0
s390x gcc 15.1.0
s390x gcc 15.2.0
sh gcc 12.2.0
sh gcc 12.3.0
sh gcc 12.4.0
sh gcc 12.5.0
sh gcc 13.1.0
sh gcc 13.2.0
sh gcc 13.3.0
sh gcc 13.4.0
sh gcc 14.1.0
sh gcc 14.2.0
sh gcc 14.3.0
sh gcc 15.1.0
sh gcc 15.2.0
sh gcc 4.9.4
sh gcc 9.5.0
vast (trunk)
x64 msvc v19.0 (ex-WINE)
x64 msvc v19.10 (ex-WINE)
x64 msvc v19.14 (ex-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.41 VS17.11
x64 msvc v19.42 VS17.12
x64 msvc v19.43 VS17.13
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 (ex-WINE)
x86 msvc v19.10 (ex-WINE)
x86 msvc v19.14 (ex-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.41 VS17.11
x86 msvc v19.42 VS17.12
x86 msvc v19.43 VS17.13
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 nvc++ 25.1
x86 nvc++ 25.3
x86 nvc++ 25.5
x86 nvc++ 25.7
x86-64 Zapcc 190308
x86-64 clang (-fimplicit-constexpr)
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 (experimental -Wlifetime)
x86-64 clang (experimental P1061)
x86-64 clang (experimental P1144)
x86-64 clang (experimental P1221)
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 P3385)
x86-64 clang (experimental P3776)
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 - C++26)
x86-64 clang (reflection - TS)
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 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 20.1.0
x86-64 clang 20.1.0 (assertions)
x86-64 clang 21.1.0
x86-64 clang 21.1.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 clang rocm-6.2.4
x86-64 clang rocm-6.3.3
x86-64 clang rocm-6.4.0
x86-64 gcc (P2034 lambdas)
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 12.5
x86-64 gcc 12.5 (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 13.4
x86-64 gcc 13.4 (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 14.3
x86-64 gcc 14.3 (assertions)
x86-64 gcc 15.1
x86-64 gcc 15.1 (assertions)
x86-64 gcc 15.2
x86-64 gcc 15.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 2024.2.1
x86-64 icx 2025.0.0
x86-64 icx 2025.0.1
x86-64 icx 2025.0.3
x86-64 icx 2025.0.4
x86-64 icx 2025.1.0
x86-64 icx 2025.1.1
x86-64 icx 2025.2.0
x86-64 icx 2025.2.1
x86-64 icx 2025.2.1
z180-clang 15.0.0
z180-clang 15.0.7
z80-clang 15.0.0
z80-clang 15.0.7
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.14.0
zig c++ 0.14.1
zig c++ 0.15.1
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
// C++11 <type_traits> -*- C++ -*- // Copyright (C) 2007-2025 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // <http://www.gnu.org/licenses/>. /** @file include/type_traits * This is a Standard C++ Library header. */ #ifndef _GLIBCXX_TYPE_TRAITS #define _GLIBCXX_TYPE_TRAITS 1 #ifdef _GLIBCXX_SYSHDR #pragma GCC system_header #endif #if __cplusplus < 201103L # include <bits/c++0x_warning.h> #else #include <bits/c++config.h> #define __glibcxx_want_bool_constant #define __glibcxx_want_bounded_array_traits #define __glibcxx_want_constant_wrapper #define __glibcxx_want_has_unique_object_representations #define __glibcxx_want_integral_constant_callable #define __glibcxx_want_is_aggregate #define __glibcxx_want_is_constant_evaluated #define __glibcxx_want_is_final #define __glibcxx_want_is_invocable #define __glibcxx_want_is_layout_compatible #define __glibcxx_want_is_nothrow_convertible #define __glibcxx_want_is_null_pointer #define __glibcxx_want_is_pointer_interconvertible #define __glibcxx_want_is_scoped_enum #define __glibcxx_want_is_swappable #define __glibcxx_want_is_virtual_base_of #define __glibcxx_want_logical_traits #define __glibcxx_want_reference_from_temporary #define __glibcxx_want_remove_cvref #define __glibcxx_want_result_of_sfinae #define __glibcxx_want_transformation_trait_aliases #define __glibcxx_want_type_identity #define __glibcxx_want_type_trait_variable_templates #define __glibcxx_want_unwrap_ref #define __glibcxx_want_void_t #include <bits/version.h> extern "C++" { namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> class reference_wrapper; /** * @defgroup metaprogramming Metaprogramming * @ingroup utilities * * Template utilities for compile-time introspection and modification, * including type classification traits, type property inspection traits * and type transformation traits. * * @since C++11 * * @{ */ /// integral_constant template<typename _Tp, _Tp __v> struct integral_constant { static constexpr _Tp value = __v; using value_type = _Tp; using type = integral_constant<_Tp, __v>; constexpr operator value_type() const noexcept { return value; } #ifdef __cpp_lib_integral_constant_callable // C++ >= 14 constexpr value_type operator()() const noexcept { return value; } #endif }; #if ! __cpp_inline_variables template<typename _Tp, _Tp __v> constexpr _Tp integral_constant<_Tp, __v>::value; #endif /// @cond undocumented /// bool_constant for C++11 template<bool __v> using __bool_constant = integral_constant<bool, __v>; /// @endcond /// The type used as a compile-time boolean with true value. using true_type = __bool_constant<true>; /// The type used as a compile-time boolean with false value. using false_type = __bool_constant<false>; #ifdef __cpp_lib_bool_constant // C++ >= 17 /// Alias template for compile-time boolean constant types. /// @since C++17 template<bool __v> using bool_constant = __bool_constant<__v>; #endif // Metaprogramming helper types. // Primary template. /// Define a member typedef `type` only if a boolean constant is true. template<bool, typename _Tp = void> struct enable_if { }; // Partial specialization for true. template<typename _Tp> struct enable_if<true, _Tp> { using type = _Tp; }; // __enable_if_t (std::enable_if_t for C++11) template<bool _Cond, typename _Tp = void> using __enable_if_t = typename enable_if<_Cond, _Tp>::type; template<bool> struct __conditional { template<typename _Tp, typename> using type = _Tp; }; template<> struct __conditional<false> { template<typename, typename _Up> using type = _Up; }; // More efficient version of std::conditional_t for internal use (and C++11) template<bool _Cond, typename _If, typename _Else> using __conditional_t = typename __conditional<_Cond>::template type<_If, _Else>; /// @cond undocumented template <typename _Type> struct __type_identity { using type = _Type; }; template<typename _Tp> using __type_identity_t = typename __type_identity<_Tp>::type; namespace __detail { // A variadic alias template that resolves to its first argument. template<typename _Tp, typename...> using __first_t = _Tp; // These are deliberately not defined. template<typename... _Bn> auto __or_fn(int) -> __first_t<false_type, __enable_if_t<!bool(_Bn::value)>...>; template<typename... _Bn> auto __or_fn(...) -> true_type; template<typename... _Bn> auto __and_fn(int) -> __first_t<true_type, __enable_if_t<bool(_Bn::value)>...>; template<typename... _Bn> auto __and_fn(...) -> false_type; } // namespace detail // Like C++17 std::dis/conjunction, but usable in C++11 and resolves // to either true_type or false_type which allows for a more efficient // implementation that avoids recursive class template instantiation. template<typename... _Bn> struct __or_ : decltype(__detail::__or_fn<_Bn...>(0)) { }; template<typename... _Bn> struct __and_ : decltype(__detail::__and_fn<_Bn...>(0)) { }; template<typename _Pp> struct __not_ : __bool_constant<!bool(_Pp::value)> { }; /// @endcond #ifdef __cpp_lib_logical_traits // C++ >= 17 /// @cond undocumented template<typename... _Bn> inline constexpr bool __or_v = __or_<_Bn...>::value; template<typename... _Bn> inline constexpr bool __and_v = __and_<_Bn...>::value; namespace __detail { template<typename /* = void */, typename _B1, typename... _Bn> struct __disjunction_impl { using type = _B1; }; template<typename _B1, typename _B2, typename... _Bn> struct __disjunction_impl<__enable_if_t<!bool(_B1::value)>, _B1, _B2, _Bn...> { using type = typename __disjunction_impl<void, _B2, _Bn...>::type; }; template<typename /* = void */, typename _B1, typename... _Bn> struct __conjunction_impl { using type = _B1; }; template<typename _B1, typename _B2, typename... _Bn> struct __conjunction_impl<__enable_if_t<bool(_B1::value)>, _B1, _B2, _Bn...> { using type = typename __conjunction_impl<void, _B2, _Bn...>::type; }; } // namespace __detail /// @endcond template<typename... _Bn> struct conjunction : __detail::__conjunction_impl<void, _Bn...>::type { }; template<> struct conjunction<> : true_type { }; template<typename... _Bn> struct disjunction : __detail::__disjunction_impl<void, _Bn...>::type { }; template<> struct disjunction<> : false_type { }; template<typename _Pp> struct negation : __not_<_Pp>::type { }; /** @ingroup variable_templates * @{ */ template<typename... _Bn> inline constexpr bool conjunction_v = conjunction<_Bn...>::value; template<typename... _Bn> inline constexpr bool disjunction_v = disjunction<_Bn...>::value; template<typename _Pp> inline constexpr bool negation_v = negation<_Pp>::value; /// @} #endif // __cpp_lib_logical_traits // Forward declarations template<typename> struct is_object; template<typename> struct remove_cv; template<typename> struct is_const; /// @cond undocumented template<typename> struct __is_array_unknown_bounds; // An object type which is not an unbounded array. // It might still be an incomplete type, but if this is false_type // then we can be certain it's not a complete object type. template<typename _Tp> using __maybe_complete_object_type = __and_<is_object<_Tp>, __not_<__is_array_unknown_bounds<_Tp>>>; // Helper functions that return false_type for incomplete classes, // incomplete unions and arrays of known bound from those. // More specialized overload for complete object types (returning true_type). template<typename _Tp, typename = __enable_if_t<__maybe_complete_object_type<_Tp>::value>, size_t = sizeof(_Tp)> constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>) { return {}; }; // Less specialized overload for reference and unknown-bound array types // (returning true_type), and incomplete types (returning false_type). template<typename _TypeIdentity, typename _NestedType = typename _TypeIdentity::type> constexpr typename __not_<__maybe_complete_object_type<_NestedType>>::type __is_complete_or_unbounded(_TypeIdentity) { return {}; } // __remove_cv_t (std::remove_cv_t for C++11). template<typename _Tp> using __remove_cv_t = typename remove_cv<_Tp>::type; /// @endcond // Primary type categories. /// is_void template<typename _Tp> struct is_void : public false_type { }; template<> struct is_void<void> : public true_type { }; template<> struct is_void<const void> : public true_type { }; template<> struct is_void<volatile void> : public true_type { }; template<> struct is_void<const volatile void> : public true_type { }; /// @cond undocumented template<typename> struct __is_integral_helper : public false_type { }; template<> struct __is_integral_helper<bool> : public true_type { }; template<> struct __is_integral_helper<char> : public true_type { }; template<> struct __is_integral_helper<signed char> : public true_type { }; template<> struct __is_integral_helper<unsigned char> : public true_type { }; // We want is_integral<wchar_t> to be true (and make_signed/unsigned to work) // even when libc doesn't provide working <wchar.h> and related functions, // so don't check _GLIBCXX_USE_WCHAR_T here. template<> struct __is_integral_helper<wchar_t> : public true_type { }; #ifdef _GLIBCXX_USE_CHAR8_T template<> struct __is_integral_helper<char8_t> : public true_type { }; #endif template<> struct __is_integral_helper<char16_t> : public true_type { }; template<> struct __is_integral_helper<char32_t> : public true_type { }; template<> struct __is_integral_helper<short> : public true_type { }; template<> struct __is_integral_helper<unsigned short> : public true_type { }; template<> struct __is_integral_helper<int> : public true_type { }; template<> struct __is_integral_helper<unsigned int> : public true_type { }; template<> struct __is_integral_helper<long> : public true_type { }; template<> struct __is_integral_helper<unsigned long> : public true_type { }; template<> struct __is_integral_helper<long long> : public true_type { }; template<> struct __is_integral_helper<unsigned long long> : public true_type { }; // Conditionalizing on __STRICT_ANSI__ here will break any port that // uses one of these types for size_t. #if defined(__GLIBCXX_TYPE_INT_N_0) __extension__ template<> struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0> : public true_type { }; __extension__ template<> struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_0> : public true_type { }; #endif #if defined(__GLIBCXX_TYPE_INT_N_1) __extension__ template<> struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1> : public true_type { }; __extension__ template<> struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_1> : public true_type { }; #endif #if defined(__GLIBCXX_TYPE_INT_N_2) __extension__ template<> struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2> : public true_type { }; __extension__ template<> struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_2> : public true_type { }; #endif #if defined(__GLIBCXX_TYPE_INT_N_3) __extension__ template<> struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3> : public true_type { }; __extension__ template<> struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_3> : public true_type { }; #endif #if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__ __extension__ template<> struct __is_integral_helper<__int128> : public true_type { }; __extension__ template<> struct __is_integral_helper<unsigned __int128> : public true_type { }; #endif /// @endcond /// is_integral template<typename _Tp> struct is_integral : public __is_integral_helper<__remove_cv_t<_Tp>>::type { }; /// @cond undocumented template<typename> struct __is_floating_point_helper : public false_type { }; template<> struct __is_floating_point_helper<float> : public true_type { }; template<> struct __is_floating_point_helper<double> : public true_type { }; template<> struct __is_floating_point_helper<long double> : public true_type { }; #ifdef __STDCPP_FLOAT16_T__ template<> struct __is_floating_point_helper<_Float16> : public true_type { }; #endif #ifdef __STDCPP_FLOAT32_T__ template<> struct __is_floating_point_helper<_Float32> : public true_type { }; #endif #ifdef __STDCPP_FLOAT64_T__ template<> struct __is_floating_point_helper<_Float64> : public true_type { }; #endif #ifdef __STDCPP_FLOAT128_T__ template<> struct __is_floating_point_helper<_Float128> : public true_type { }; #endif #ifdef __STDCPP_BFLOAT16_T__ template<> struct __is_floating_point_helper<__gnu_cxx::__bfloat16_t> : public true_type { }; #endif #ifdef _GLIBCXX_USE_FLOAT128 template<> struct __is_floating_point_helper<__float128> : public true_type { }; #endif /// @endcond /// is_floating_point template<typename _Tp> struct is_floating_point : public __is_floating_point_helper<__remove_cv_t<_Tp>>::type { }; /// is_array #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_array) template<typename _Tp> struct is_array : public __bool_constant<__is_array(_Tp)> { }; #else template<typename> struct is_array : public false_type { }; template<typename _Tp, std::size_t _Size> struct is_array<_Tp[_Size]> : public true_type { }; template<typename _Tp> struct is_array<_Tp[]> : public true_type { }; #endif /// is_pointer #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_pointer) template<typename _Tp> struct is_pointer : public __bool_constant<__is_pointer(_Tp)> { }; #else template<typename _Tp> struct is_pointer : public false_type { }; template<typename _Tp> struct is_pointer<_Tp*> : public true_type { }; template<typename _Tp> struct is_pointer<_Tp* const> : public true_type { }; template<typename _Tp> struct is_pointer<_Tp* volatile> : public true_type { }; template<typename _Tp> struct is_pointer<_Tp* const volatile> : public true_type { }; #endif /// is_lvalue_reference template<typename> struct is_lvalue_reference : public false_type { }; template<typename _Tp> struct is_lvalue_reference<_Tp&> : public true_type { }; /// is_rvalue_reference template<typename> struct is_rvalue_reference : public false_type { }; template<typename _Tp> struct is_rvalue_reference<_Tp&&> : public true_type { }; /// is_member_object_pointer #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_object_pointer) template<typename _Tp> struct is_member_object_pointer : public __bool_constant<__is_member_object_pointer(_Tp)> { }; #else template<typename> struct __is_member_object_pointer_helper : public false_type { }; template<typename _Tp, typename _Cp> struct __is_member_object_pointer_helper<_Tp _Cp::*> : public __not_<is_function<_Tp>>::type { }; template<typename _Tp> struct is_member_object_pointer : public __is_member_object_pointer_helper<__remove_cv_t<_Tp>>::type { }; #endif #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer) /// is_member_function_pointer template<typename _Tp> struct is_member_function_pointer : public __bool_constant<__is_member_function_pointer(_Tp)> { }; #else template<typename> struct __is_member_function_pointer_helper : public false_type { }; template<typename _Tp, typename _Cp> struct __is_member_function_pointer_helper<_Tp _Cp::*> : public is_function<_Tp>::type { }; /// is_member_function_pointer template<typename _Tp> struct is_member_function_pointer : public __is_member_function_pointer_helper<__remove_cv_t<_Tp>>::type { }; #endif /// is_enum template<typename _Tp> struct is_enum : public __bool_constant<__is_enum(_Tp)> { }; /// is_union template<typename _Tp> struct is_union : public __bool_constant<__is_union(_Tp)> { }; /// is_class template<typename _Tp> struct is_class : public __bool_constant<__is_class(_Tp)> { }; /// is_function #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function) template<typename _Tp> struct is_function : public __bool_constant<__is_function(_Tp)> { }; #else template<typename _Tp> struct is_function : public __bool_constant<!is_const<const _Tp>::value> { }; template<typename _Tp> struct is_function<_Tp&> : public false_type { }; template<typename _Tp> struct is_function<_Tp&&> : public false_type { }; #endif #ifdef __cpp_lib_is_null_pointer // C++ >= 11 /// is_null_pointer (LWG 2247). template<typename _Tp> struct is_null_pointer : public false_type { }; template<> struct is_null_pointer<std::nullptr_t> : public true_type { }; template<> struct is_null_pointer<const std::nullptr_t> : public true_type { }; template<> struct is_null_pointer<volatile std::nullptr_t> : public true_type { }; template<> struct is_null_pointer<const volatile std::nullptr_t> : public true_type { }; /// __is_nullptr_t (deprecated extension). /// @deprecated Non-standard. Use `is_null_pointer` instead. template<typename _Tp> struct __is_nullptr_t : public is_null_pointer<_Tp> { } _GLIBCXX_DEPRECATED_SUGGEST("std::is_null_pointer"); #endif // __cpp_lib_is_null_pointer // Composite type categories. /// is_reference #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference) template<typename _Tp> struct is_reference : public __bool_constant<__is_reference(_Tp)> { }; #else template<typename _Tp> struct is_reference : public false_type { }; template<typename _Tp> struct is_reference<_Tp&> : public true_type { }; template<typename _Tp> struct is_reference<_Tp&&> : public true_type { }; #endif /// is_arithmetic template<typename _Tp> struct is_arithmetic : public __or_<is_integral<_Tp>, is_floating_point<_Tp>>::type { }; /// is_fundamental template<typename _Tp> struct is_fundamental : public __or_<is_arithmetic<_Tp>, is_void<_Tp>, is_null_pointer<_Tp>>::type { }; /// is_object #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_object) template<typename _Tp> struct is_object : public __bool_constant<__is_object(_Tp)> { }; #else template<typename _Tp> struct is_object : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>, is_void<_Tp>>>::type { }; #endif template<typename> struct is_member_pointer; /// is_scalar template<typename _Tp> struct is_scalar : public __or_<is_arithmetic<_Tp>, is_enum<_Tp>, is_pointer<_Tp>, is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type { }; /// is_compound template<typename _Tp> struct is_compound : public __bool_constant<!is_fundamental<_Tp>::value> { }; /// is_member_pointer #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer) template<typename _Tp> struct is_member_pointer : public __bool_constant<__is_member_pointer(_Tp)> { }; #else /// @cond undocumented template<typename _Tp> struct __is_member_pointer_helper : public false_type { }; template<typename _Tp, typename _Cp> struct __is_member_pointer_helper<_Tp _Cp::*> : public true_type { }; /// @endcond template<typename _Tp> struct is_member_pointer : public __is_member_pointer_helper<__remove_cv_t<_Tp>>::type { }; #endif template<typename, typename> struct is_same; /// @cond undocumented template<typename _Tp, typename... _Types> using __is_one_of = __or_<is_same<_Tp, _Types>...>; // Check if a type is one of the signed integer types. __extension__ template<typename _Tp> using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>, signed char, signed short, signed int, signed long, signed long long #if defined(__GLIBCXX_TYPE_INT_N_0) , signed __GLIBCXX_TYPE_INT_N_0 #endif #if defined(__GLIBCXX_TYPE_INT_N_1) , signed __GLIBCXX_TYPE_INT_N_1 #endif #if defined(__GLIBCXX_TYPE_INT_N_2) , signed __GLIBCXX_TYPE_INT_N_2 #endif #if defined(__GLIBCXX_TYPE_INT_N_3) , signed __GLIBCXX_TYPE_INT_N_3 #endif >; // Check if a type is one of the unsigned integer types. __extension__ template<typename _Tp> using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long #if defined(__GLIBCXX_TYPE_INT_N_0) , unsigned __GLIBCXX_TYPE_INT_N_0 #endif #if defined(__GLIBCXX_TYPE_INT_N_1) , unsigned __GLIBCXX_TYPE_INT_N_1 #endif #if defined(__GLIBCXX_TYPE_INT_N_2) , unsigned __GLIBCXX_TYPE_INT_N_2 #endif #if defined(__GLIBCXX_TYPE_INT_N_3) , unsigned __GLIBCXX_TYPE_INT_N_3 #endif >; // Check if a type is one of the signed or unsigned integer types. template<typename _Tp> using __is_standard_integer = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>; // __void_t (std::void_t for C++11) template<typename...> using __void_t = void; /// @endcond // Type properties. /// is_const #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_const) template<typename _Tp> struct is_const : public __bool_constant<__is_const(_Tp)> { }; #else template<typename> struct is_const : public false_type { }; template<typename _Tp> struct is_const<_Tp const> : public true_type { }; #endif /// is_volatile #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_volatile) template<typename _Tp> struct is_volatile : public __bool_constant<__is_volatile(_Tp)> { }; #else template<typename> struct is_volatile : public false_type { }; template<typename _Tp> struct is_volatile<_Tp volatile> : public true_type { }; #endif /** is_trivial * @deprecated Deprecated in C++26. * Use a combination of one or more more specialized type traits instead, * such as `is_trivially_default_constructible`, * `is_trivially_copy_constructible`, `is_trivially_copy_assignable`, * etc., depending on the exact check(s) needed. */ template<typename _Tp> struct _GLIBCXX26_DEPRECATED_SUGGEST("is_trivially_default_constructible && is_trivially_copyable") is_trivial : public __bool_constant<__is_trivial(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_trivially_copyable template<typename _Tp> struct is_trivially_copyable : public __bool_constant<__is_trivially_copyable(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_standard_layout template<typename _Tp> struct is_standard_layout : public __bool_constant<__is_standard_layout(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /** is_pod * @deprecated Deprecated in C++20. * Use `is_standard_layout && is_trivial` instead. */ // Could use is_standard_layout && is_trivial instead of the builtin. template<typename _Tp> struct _GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout && is_trivial") is_pod : public __bool_constant<__is_pod(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /** is_literal_type * @deprecated Deprecated in C++17, removed in C++20. * The idea of a literal type isn't useful. */ template<typename _Tp> struct _GLIBCXX17_DEPRECATED is_literal_type : public __bool_constant<__is_literal_type(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_empty template<typename _Tp> struct is_empty : public __bool_constant<__is_empty(_Tp)> { }; /// is_polymorphic template<typename _Tp> struct is_polymorphic : public __bool_constant<__is_polymorphic(_Tp)> { }; #ifdef __cpp_lib_is_final // C++ >= 14 /// is_final /// @since C++14 template<typename _Tp> struct is_final : public __bool_constant<__is_final(_Tp)> { }; #endif /// is_abstract template<typename _Tp> struct is_abstract : public __bool_constant<__is_abstract(_Tp)> { }; /// @cond undocumented template<typename _Tp, bool = is_arithmetic<_Tp>::value> struct __is_signed_helper : public false_type { }; template<typename _Tp> struct __is_signed_helper<_Tp, true> : public __bool_constant<_Tp(-1) < _Tp(0)> { }; /// @endcond /// is_signed template<typename _Tp> struct is_signed : public __is_signed_helper<_Tp>::type { }; /// is_unsigned template<typename _Tp> struct is_unsigned : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type { }; /// @cond undocumented template<typename _Tp, typename _Up = _Tp&&> _Up __declval(int); template<typename _Tp> _Tp __declval(long); /// @endcond template<typename _Tp> auto declval() noexcept -> decltype(__declval<_Tp>(0)); template<typename> struct remove_all_extents; /// @cond undocumented template<typename _Tp> struct __is_array_known_bounds : public false_type { }; template<typename _Tp, size_t _Size> struct __is_array_known_bounds<_Tp[_Size]> : public true_type { }; template<typename _Tp> struct __is_array_unknown_bounds : public false_type { }; template<typename _Tp> struct __is_array_unknown_bounds<_Tp[]> : public true_type { }; /// @endcond // Destructible and constructible type properties. #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_destructible) /// is_destructible template<typename _Tp> struct is_destructible : public __bool_constant<__is_destructible(_Tp)> { }; #else /// @cond undocumented // In N3290 is_destructible does not say anything about function // types and abstract types, see LWG 2049. This implementation // describes function types as non-destructible and all complete // object types as destructible, iff the explicit destructor // call expression is wellformed. struct __do_is_destructible_impl { template<typename _Tp, typename = decltype(declval<_Tp&>().~_Tp())> static true_type __test(int); template<typename> static false_type __test(...); }; template<typename _Tp> struct __is_destructible_impl : public __do_is_destructible_impl { using type = decltype(__test<_Tp>(0)); }; template<typename _Tp, bool = __or_<is_void<_Tp>, __is_array_unknown_bounds<_Tp>, is_function<_Tp>>::value, bool = __or_<is_reference<_Tp>, is_scalar<_Tp>>::value> struct __is_destructible_safe; template<typename _Tp> struct __is_destructible_safe<_Tp, false, false> : public __is_destructible_impl<typename remove_all_extents<_Tp>::type>::type { }; template<typename _Tp> struct __is_destructible_safe<_Tp, true, false> : public false_type { }; template<typename _Tp> struct __is_destructible_safe<_Tp, false, true> : public true_type { }; /// @endcond /// is_destructible template<typename _Tp> struct is_destructible : public __is_destructible_safe<_Tp>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; #endif #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_destructible) /// is_nothrow_destructible template<typename _Tp> struct is_nothrow_destructible : public __bool_constant<__is_nothrow_destructible(_Tp)> { }; #else /// @cond undocumented // is_nothrow_destructible requires that is_destructible is // satisfied as well. We realize that by mimicing the // implementation of is_destructible but refer to noexcept(expr) // instead of decltype(expr). struct __do_is_nt_destructible_impl { template<typename _Tp> static __bool_constant<noexcept(declval<_Tp&>().~_Tp())> __test(int); template<typename> static false_type __test(...); }; template<typename _Tp> struct __is_nt_destructible_impl : public __do_is_nt_destructible_impl { using type = decltype(__test<_Tp>(0)); }; template<typename _Tp, bool = __or_<is_void<_Tp>, __is_array_unknown_bounds<_Tp>, is_function<_Tp>>::value, bool = __or_<is_reference<_Tp>, is_scalar<_Tp>>::value> struct __is_nt_destructible_safe; template<typename _Tp> struct __is_nt_destructible_safe<_Tp, false, false> : public __is_nt_destructible_impl<typename remove_all_extents<_Tp>::type>::type { }; template<typename _Tp> struct __is_nt_destructible_safe<_Tp, true, false> : public false_type { }; template<typename _Tp> struct __is_nt_destructible_safe<_Tp, false, true> : public true_type { }; /// @endcond /// is_nothrow_destructible template<typename _Tp> struct is_nothrow_destructible : public __is_nt_destructible_safe<_Tp>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; #endif /// @cond undocumented template<typename _Tp, typename... _Args> using __is_constructible_impl = __bool_constant<__is_constructible(_Tp, _Args...)>; /// @endcond /// is_constructible template<typename _Tp, typename... _Args> struct is_constructible : public __is_constructible_impl<_Tp, _Args...> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_default_constructible template<typename _Tp> struct is_default_constructible : public __is_constructible_impl<_Tp> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// @cond undocumented #if _GLIBCXX_USE_BUILTIN_TRAIT(__add_lvalue_reference) template<typename _Tp> using __add_lval_ref_t = __add_lvalue_reference(_Tp); #else template<typename _Tp, typename = void> struct __add_lvalue_reference_helper { using type = _Tp; }; template<typename _Tp> struct __add_lvalue_reference_helper<_Tp, __void_t<_Tp&>> { using type = _Tp&; }; template<typename _Tp> using __add_lval_ref_t = typename __add_lvalue_reference_helper<_Tp>::type; #endif /// @endcond /// is_copy_constructible template<typename _Tp> struct is_copy_constructible : public __is_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// @cond undocumented #if _GLIBCXX_USE_BUILTIN_TRAIT(__add_rvalue_reference) template<typename _Tp> using __add_rval_ref_t = __add_rvalue_reference(_Tp); #else template<typename _Tp, typename = void> struct __add_rvalue_reference_helper { using type = _Tp; }; template<typename _Tp> struct __add_rvalue_reference_helper<_Tp, __void_t<_Tp&&>> { using type = _Tp&&; }; template<typename _Tp> using __add_rval_ref_t = typename __add_rvalue_reference_helper<_Tp>::type; #endif /// @endcond /// is_move_constructible template<typename _Tp> struct is_move_constructible : public __is_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// @cond undocumented template<typename _Tp, typename... _Args> using __is_nothrow_constructible_impl = __bool_constant<__is_nothrow_constructible(_Tp, _Args...)>; /// @endcond /// is_nothrow_constructible template<typename _Tp, typename... _Args> struct is_nothrow_constructible : public __is_nothrow_constructible_impl<_Tp, _Args...> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_nothrow_default_constructible template<typename _Tp> struct is_nothrow_default_constructible : public __is_nothrow_constructible_impl<_Tp> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_nothrow_copy_constructible template<typename _Tp> struct is_nothrow_copy_constructible : public __is_nothrow_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_nothrow_move_constructible template<typename _Tp> struct is_nothrow_move_constructible : public __is_nothrow_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// @cond undocumented template<typename _Tp, typename _Up> using __is_assignable_impl = __bool_constant<__is_assignable(_Tp, _Up)>; /// @endcond /// is_assignable template<typename _Tp, typename _Up> struct is_assignable : public __is_assignable_impl<_Tp, _Up> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_copy_assignable template<typename _Tp> struct is_copy_assignable : public __is_assignable_impl<__add_lval_ref_t<_Tp>, __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_move_assignable template<typename _Tp> struct is_move_assignable : public __is_assignable_impl<__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// @cond undocumented template<typename _Tp, typename _Up> using __is_nothrow_assignable_impl = __bool_constant<__is_nothrow_assignable(_Tp, _Up)>; /// @endcond /// is_nothrow_assignable template<typename _Tp, typename _Up> struct is_nothrow_assignable : public __is_nothrow_assignable_impl<_Tp, _Up> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_nothrow_copy_assignable template<typename _Tp> struct is_nothrow_copy_assignable : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>, __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_nothrow_move_assignable template<typename _Tp> struct is_nothrow_move_assignable : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// @cond undocumented template<typename _Tp, typename... _Args> using __is_trivially_constructible_impl = __bool_constant<__is_trivially_constructible(_Tp, _Args...)>; /// @endcond /// is_trivially_constructible template<typename _Tp, typename... _Args> struct is_trivially_constructible : public __is_trivially_constructible_impl<_Tp, _Args...> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_trivially_default_constructible template<typename _Tp> struct is_trivially_default_constructible : public __is_trivially_constructible_impl<_Tp> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; #if __cpp_variable_templates && __cpp_concepts template<typename _Tp> constexpr bool __is_implicitly_default_constructible_v = requires (void(&__f)(_Tp)) { __f({}); }; template<typename _Tp> struct __is_implicitly_default_constructible : __bool_constant<__is_implicitly_default_constructible_v<_Tp>> { }; #else struct __do_is_implicitly_default_constructible_impl { template <typename _Tp> static void __helper(const _Tp&); template <typename _Tp> static true_type __test(const _Tp&, decltype(__helper<const _Tp&>({}))* = 0); static false_type __test(...); }; template<typename _Tp> struct __is_implicitly_default_constructible_impl : public __do_is_implicitly_default_constructible_impl { using type = decltype(__test(declval<_Tp>())); }; template<typename _Tp> struct __is_implicitly_default_constructible_safe : public __is_implicitly_default_constructible_impl<_Tp>::type { }; template <typename _Tp> struct __is_implicitly_default_constructible : public __and_<__is_constructible_impl<_Tp>, __is_implicitly_default_constructible_safe<_Tp>>::type { }; #endif /// is_trivially_copy_constructible template<typename _Tp> struct is_trivially_copy_constructible : public __is_trivially_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_trivially_move_constructible template<typename _Tp> struct is_trivially_move_constructible : public __is_trivially_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// @cond undocumented template<typename _Tp, typename _Up> using __is_trivially_assignable_impl = __bool_constant<__is_trivially_assignable(_Tp, _Up)>; /// @endcond /// is_trivially_assignable template<typename _Tp, typename _Up> struct is_trivially_assignable : public __is_trivially_assignable_impl<_Tp, _Up> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_trivially_copy_assignable template<typename _Tp> struct is_trivially_copy_assignable : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>, __add_lval_ref_t<const _Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_trivially_move_assignable template<typename _Tp> struct is_trivially_move_assignable : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_trivially_destructible) /// is_trivially_destructible template<typename _Tp> struct is_trivially_destructible : public __bool_constant<__is_trivially_destructible(_Tp)> { }; #else /// is_trivially_destructible template<typename _Tp> struct is_trivially_destructible : public __and_<__is_destructible_safe<_Tp>, __bool_constant<__has_trivial_destructor(_Tp)>>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; #endif /// has_virtual_destructor template<typename _Tp> struct has_virtual_destructor : public __bool_constant<__has_virtual_destructor(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; // type property queries. /// alignment_of template<typename _Tp> struct alignment_of : public integral_constant<std::size_t, alignof(_Tp)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// rank #if _GLIBCXX_USE_BUILTIN_TRAIT(__array_rank) \ && (!defined(__clang__) || __clang_major__ >= 20) // PR118559 template<typename _Tp> struct rank : public integral_constant<std::size_t, __array_rank(_Tp)> { }; #else template<typename> struct rank : public integral_constant<std::size_t, 0> { }; template<typename _Tp, std::size_t _Size> struct rank<_Tp[_Size]> : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { }; template<typename _Tp> struct rank<_Tp[]> : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { }; #endif /// extent template<typename, unsigned _Uint = 0> struct extent : public integral_constant<size_t, 0> { }; template<typename _Tp, size_t _Size> struct extent<_Tp[_Size], 0> : public integral_constant<size_t, _Size> { }; template<typename _Tp, unsigned _Uint, size_t _Size> struct extent<_Tp[_Size], _Uint> : public extent<_Tp, _Uint - 1>::type { }; template<typename _Tp> struct extent<_Tp[], 0> : public integral_constant<size_t, 0> { }; template<typename _Tp, unsigned _Uint> struct extent<_Tp[], _Uint> : public extent<_Tp, _Uint - 1>::type { }; // Type relations. /// is_same #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_same) template<typename _Tp, typename _Up> struct is_same : public __bool_constant<__is_same(_Tp, _Up)> { }; #else template<typename _Tp, typename _Up> struct is_same : public false_type { }; template<typename _Tp> struct is_same<_Tp, _Tp> : public true_type { }; #endif /// is_base_of template<typename _Base, typename _Derived> struct is_base_of : public __bool_constant<__is_base_of(_Base, _Derived)> { }; #ifdef __cpp_lib_is_virtual_base_of // C++ >= 26 /// is_virtual_base_of /// @since C++26 template<typename _Base, typename _Derived> struct is_virtual_base_of : public bool_constant<__builtin_is_virtual_base_of(_Base, _Derived)> { }; #endif #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_convertible) template<typename _From, typename _To> struct is_convertible : public __bool_constant<__is_convertible(_From, _To)> { }; #else template<typename _From, typename _To, bool = __or_<is_void<_From>, is_function<_To>, is_array<_To>>::value> struct __is_convertible_helper { using type = typename is_void<_To>::type; }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" template<typename _From, typename _To> class __is_convertible_helper<_From, _To, false> { template<typename _To1> static void __test_aux(_To1) noexcept; template<typename _From1, typename _To1, typename = decltype(__test_aux<_To1>(std::declval<_From1>()))> static true_type __test(int); template<typename, typename> static false_type __test(...); public: using type = decltype(__test<_From, _To>(0)); }; #pragma GCC diagnostic pop /// is_convertible template<typename _From, typename _To> struct is_convertible : public __is_convertible_helper<_From, _To>::type { }; #endif // helper trait for unique_ptr<T[]>, shared_ptr<T[]>, and span<T, N> template<typename _ToElementType, typename _FromElementType> using __is_array_convertible = is_convertible<_FromElementType(*)[], _ToElementType(*)[]>; #ifdef __cpp_lib_is_nothrow_convertible // C++ >= 20 #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_convertible) /// is_nothrow_convertible_v template<typename _From, typename _To> inline constexpr bool is_nothrow_convertible_v = __is_nothrow_convertible(_From, _To); /// is_nothrow_convertible template<typename _From, typename _To> struct is_nothrow_convertible : public bool_constant<is_nothrow_convertible_v<_From, _To>> { }; #else template<typename _From, typename _To, bool = __or_<is_void<_From>, is_function<_To>, is_array<_To>>::value> struct __is_nt_convertible_helper : is_void<_To> { }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" template<typename _From, typename _To> class __is_nt_convertible_helper<_From, _To, false> { template<typename _To1> static void __test_aux(_To1) noexcept; template<typename _From1, typename _To1> static __bool_constant<noexcept(__test_aux<_To1>(std::declval<_From1>()))> __test(int); template<typename, typename> static false_type __test(...); public: using type = decltype(__test<_From, _To>(0)); }; #pragma GCC diagnostic pop /// is_nothrow_convertible template<typename _From, typename _To> struct is_nothrow_convertible : public __is_nt_convertible_helper<_From, _To>::type { }; /// is_nothrow_convertible_v template<typename _From, typename _To> inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<_From, _To>::value; #endif #endif // __cpp_lib_is_nothrow_convertible #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wc++14-extensions" // for variable templates template<typename _Tp, typename... _Args> struct __is_nothrow_new_constructible_impl : __bool_constant< noexcept(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...)) > { }; template<typename _Tp, typename... _Args> _GLIBCXX17_INLINE constexpr bool __is_nothrow_new_constructible = __and_<is_constructible<_Tp, _Args...>, __is_nothrow_new_constructible_impl<_Tp, _Args...>>::value; #pragma GCC diagnostic pop // Const-volatile modifications. /// remove_const template<typename _Tp> struct remove_const { using type = _Tp; }; template<typename _Tp> struct remove_const<_Tp const> { using type = _Tp; }; /// remove_volatile template<typename _Tp> struct remove_volatile { using type = _Tp; }; template<typename _Tp> struct remove_volatile<_Tp volatile> { using type = _Tp; }; /// remove_cv #if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_cv) template<typename _Tp> struct remove_cv { using type = __remove_cv(_Tp); }; #else template<typename _Tp> struct remove_cv { using type = _Tp; }; template<typename _Tp> struct remove_cv<const _Tp> { using type = _Tp; }; template<typename _Tp> struct remove_cv<volatile _Tp> { using type = _Tp; }; template<typename _Tp> struct remove_cv<const volatile _Tp> { using type = _Tp; }; #endif /// add_const template<typename _Tp> struct add_const { using type = _Tp const; }; /// add_volatile template<typename _Tp> struct add_volatile { using type = _Tp volatile; }; /// add_cv template<typename _Tp> struct add_cv { using type = _Tp const volatile; }; #ifdef __cpp_lib_transformation_trait_aliases // C++ >= 14 /// Alias template for remove_const template<typename _Tp> using remove_const_t = typename remove_const<_Tp>::type; /// Alias template for remove_volatile template<typename _Tp> using remove_volatile_t = typename remove_volatile<_Tp>::type; /// Alias template for remove_cv template<typename _Tp> using remove_cv_t = typename remove_cv<_Tp>::type; /// Alias template for add_const template<typename _Tp> using add_const_t = typename add_const<_Tp>::type; /// Alias template for add_volatile template<typename _Tp> using add_volatile_t = typename add_volatile<_Tp>::type; /// Alias template for add_cv template<typename _Tp> using add_cv_t = typename add_cv<_Tp>::type; #endif // Reference transformations. /// remove_reference #if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_reference) template<typename _Tp> struct remove_reference { using type = __remove_reference(_Tp); }; #else template<typename _Tp> struct remove_reference { using type = _Tp; }; template<typename _Tp> struct remove_reference<_Tp&> { using type = _Tp; }; template<typename _Tp> struct remove_reference<_Tp&&> { using type = _Tp; }; #endif /// add_lvalue_reference template<typename _Tp> struct add_lvalue_reference { using type = __add_lval_ref_t<_Tp>; }; /// add_rvalue_reference template<typename _Tp> struct add_rvalue_reference { using type = __add_rval_ref_t<_Tp>; }; #if __cplusplus > 201103L /// Alias template for remove_reference template<typename _Tp> using remove_reference_t = typename remove_reference<_Tp>::type; /// Alias template for add_lvalue_reference template<typename _Tp> using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type; /// Alias template for add_rvalue_reference template<typename _Tp> using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type; #endif // Sign modifications. /// @cond undocumented // Utility for constructing identically cv-qualified types. template<typename _Unqualified, bool _IsConst, bool _IsVol> struct __cv_selector; template<typename _Unqualified> struct __cv_selector<_Unqualified, false, false> { using __type = _Unqualified; }; template<typename _Unqualified> struct __cv_selector<_Unqualified, false, true> { using __type = volatile _Unqualified; }; template<typename _Unqualified> struct __cv_selector<_Unqualified, true, false> { using __type = const _Unqualified; }; template<typename _Unqualified> struct __cv_selector<_Unqualified, true, true> { using __type = const volatile _Unqualified; }; template<typename _Qualified, typename _Unqualified, bool _IsConst = is_const<_Qualified>::value, bool _IsVol = is_volatile<_Qualified>::value> class __match_cv_qualifiers { using __match = __cv_selector<_Unqualified, _IsConst, _IsVol>; public: using __type = typename __match::__type; }; // Utility for finding the unsigned versions of signed integral types. template<typename _Tp> struct __make_unsigned_impl { using __type = _Tp; }; template<> struct __make_unsigned_impl<char> { using __type = unsigned char; }; template<> struct __make_unsigned_impl<signed char> { using __type = unsigned char; }; template<> struct __make_unsigned_impl<short> { using __type = unsigned short; }; template<> struct __make_unsigned_impl<int> { using __type = unsigned int; }; template<> struct __make_unsigned_impl<long> { using __type = unsigned long; }; template<> struct __make_unsigned_impl<long long> { using __type = unsigned long long; }; #if defined(__GLIBCXX_TYPE_INT_N_0) __extension__ template<> struct __make_unsigned_impl<__GLIBCXX_TYPE_INT_N_0> { using __type = unsigned __GLIBCXX_TYPE_INT_N_0; }; #endif #if defined(__GLIBCXX_TYPE_INT_N_1) __extension__ template<> struct __make_unsigned_impl<__GLIBCXX_TYPE_INT_N_1> { using __type = unsigned __GLIBCXX_TYPE_INT_N_1; }; #endif #if defined(__GLIBCXX_TYPE_INT_N_2) __extension__ template<> struct __make_unsigned_impl<__GLIBCXX_TYPE_INT_N_2> { using __type = unsigned __GLIBCXX_TYPE_INT_N_2; }; #endif #if defined(__GLIBCXX_TYPE_INT_N_3) __extension__ template<> struct __make_unsigned_impl<__GLIBCXX_TYPE_INT_N_3> { using __type = unsigned __GLIBCXX_TYPE_INT_N_3; }; #endif #if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__ __extension__ template<> struct __make_unsigned_impl<__int128> { using __type = unsigned __int128; }; #endif // Select between integral and enum: not possible to be both. template<typename _Tp, bool _IsInt = is_integral<_Tp>::value, bool _IsEnum = __is_enum(_Tp)> class __make_unsigned_selector; template<typename _Tp> class __make_unsigned_selector<_Tp, true, false> { using __unsigned_type = typename __make_unsigned_impl<__remove_cv_t<_Tp>>::__type; public: using __type = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; }; class __make_unsigned_selector_base { protected: template<typename...> struct _List { }; template<typename _Tp, typename... _Up> struct _List<_Tp, _Up...> : _List<_Up...> { static constexpr size_t __size = sizeof(_Tp); }; template<size_t _Sz, typename _Tp, bool = (_Sz <= _Tp::__size)> struct __select; template<size_t _Sz, typename _Uint, typename... _UInts> struct __select<_Sz, _List<_Uint, _UInts...>, true> { using __type = _Uint; }; template<size_t _Sz, typename _Uint, typename... _UInts> struct __select<_Sz, _List<_Uint, _UInts...>, false> : __select<_Sz, _List<_UInts...>> { }; }; // Choose unsigned integer type with the smallest rank and same size as _Tp template<typename _Tp> class __make_unsigned_selector<_Tp, false, true> : __make_unsigned_selector_base { // With -fshort-enums, an enum may be as small as a char. __extension__ using _UInts = _List<unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long #ifdef __SIZEOF_INT128__ , unsigned __int128 #endif >; using __unsigned_type = typename __select<sizeof(_Tp), _UInts>::__type; public: using __type = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; }; // wchar_t, char8_t, char16_t and char32_t are integral types but are // neither signed integer types nor unsigned integer types, so must be // transformed to the unsigned integer type with the smallest rank. // Use the partial specialization for enumeration types to do that. template<> struct __make_unsigned_impl<wchar_t> { using __type = typename __make_unsigned_selector<wchar_t, false, true>::__type; }; #ifdef _GLIBCXX_USE_CHAR8_T template<> struct __make_unsigned_impl<char8_t> { using __type = typename __make_unsigned_selector<char8_t, false, true>::__type; }; #endif template<> struct __make_unsigned_impl<char16_t> { using __type = typename __make_unsigned_selector<char16_t, false, true>::__type; }; template<> struct __make_unsigned_impl<char32_t> { using __type = typename __make_unsigned_selector<char32_t, false, true>::__type; }; /// @endcond // Given an integral/enum type, return the corresponding unsigned // integer type. // Primary template. /// make_unsigned template<typename _Tp> struct make_unsigned { using type = typename __make_unsigned_selector<_Tp>::__type; }; // Integral, but don't define. template<> struct make_unsigned<bool>; template<> struct make_unsigned<bool const>; template<> struct make_unsigned<bool volatile>; template<> struct make_unsigned<bool const volatile>; /// @cond undocumented // Utility for finding the signed versions of unsigned integral types. template<typename _Tp> struct __make_signed_impl { using __type = _Tp; }; template<> struct __make_signed_impl<char> { using __type = signed char; }; template<> struct __make_signed_impl<unsigned char> { using __type = signed char; }; template<> struct __make_signed_impl<unsigned short> { using __type = signed short; }; template<> struct __make_signed_impl<unsigned int> { using __type = signed int; }; template<> struct __make_signed_impl<unsigned long> { using __type = signed long; }; template<> struct __make_signed_impl<unsigned long long> { using __type = signed long long; }; #if defined(__GLIBCXX_TYPE_INT_N_0) __extension__ template<> struct __make_signed_impl<unsigned __GLIBCXX_TYPE_INT_N_0> { using __type = __GLIBCXX_TYPE_INT_N_0; }; #endif #if defined(__GLIBCXX_TYPE_INT_N_1) __extension__ template<> struct __make_signed_impl<unsigned __GLIBCXX_TYPE_INT_N_1> { using __type = __GLIBCXX_TYPE_INT_N_1; }; #endif #if defined(__GLIBCXX_TYPE_INT_N_2) __extension__ template<> struct __make_signed_impl<unsigned __GLIBCXX_TYPE_INT_N_2> { using __type = __GLIBCXX_TYPE_INT_N_2; }; #endif #if defined(__GLIBCXX_TYPE_INT_N_3) __extension__ template<> struct __make_signed_impl<unsigned __GLIBCXX_TYPE_INT_N_3> { using __type = __GLIBCXX_TYPE_INT_N_3; }; #endif #if defined __SIZEOF_INT128__ && defined __STRICT_ANSI__ __extension__ template<> struct __make_signed_impl<unsigned __int128> { using __type = __int128; }; #endif // Select between integral and enum: not possible to be both. template<typename _Tp, bool _IsInt = is_integral<_Tp>::value, bool _IsEnum = __is_enum(_Tp)> class __make_signed_selector; template<typename _Tp> class __make_signed_selector<_Tp, true, false> { using __signed_type = typename __make_signed_impl<__remove_cv_t<_Tp>>::__type; public: using __type = typename __match_cv_qualifiers<_Tp, __signed_type>::__type; }; // Choose signed integer type with the smallest rank and same size as _Tp template<typename _Tp> class __make_signed_selector<_Tp, false, true> { using __unsigned_type = typename __make_unsigned_selector<_Tp>::__type; public: using __type = typename __make_signed_selector<__unsigned_type>::__type; }; // wchar_t, char16_t and char32_t are integral types but are neither // signed integer types nor unsigned integer types, so must be // transformed to the signed integer type with the smallest rank. // Use the partial specialization for enumeration types to do that. template<> struct __make_signed_impl<wchar_t> { using __type = typename __make_signed_selector<wchar_t, false, true>::__type; }; #if defined(_GLIBCXX_USE_CHAR8_T) template<> struct __make_signed_impl<char8_t> { using __type = typename __make_signed_selector<char8_t, false, true>::__type; }; #endif template<> struct __make_signed_impl<char16_t> { using __type = typename __make_signed_selector<char16_t, false, true>::__type; }; template<> struct __make_signed_impl<char32_t> { using __type = typename __make_signed_selector<char32_t, false, true>::__type; }; /// @endcond // Given an integral/enum type, return the corresponding signed // integer type. // Primary template. /// make_signed template<typename _Tp> struct make_signed { using type = typename __make_signed_selector<_Tp>::__type; }; // Integral, but don't define. template<> struct make_signed<bool>; template<> struct make_signed<bool const>; template<> struct make_signed<bool volatile>; template<> struct make_signed<bool const volatile>; #if __cplusplus > 201103L /// Alias template for make_signed template<typename _Tp> using make_signed_t = typename make_signed<_Tp>::type; /// Alias template for make_unsigned template<typename _Tp> using make_unsigned_t = typename make_unsigned<_Tp>::type; #endif // Array modifications. /// remove_extent #if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_extent) template<typename _Tp> struct remove_extent { using type = __remove_extent(_Tp); }; #else template<typename _Tp> struct remove_extent { using type = _Tp; }; template<typename _Tp, std::size_t _Size> struct remove_extent<_Tp[_Size]> { using type = _Tp; }; template<typename _Tp> struct remove_extent<_Tp[]> { using type = _Tp; }; #endif /// remove_all_extents #if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_all_extents) template<typename _Tp> struct remove_all_extents { using type = __remove_all_extents(_Tp); }; #else template<typename _Tp> struct remove_all_extents { using type = _Tp; }; template<typename _Tp, std::size_t _Size> struct remove_all_extents<_Tp[_Size]> { using type = typename remove_all_extents<_Tp>::type; }; template<typename _Tp> struct remove_all_extents<_Tp[]> { using type = typename remove_all_extents<_Tp>::type; }; #endif #if __cplusplus > 201103L /// Alias template for remove_extent template<typename _Tp> using remove_extent_t = typename remove_extent<_Tp>::type; /// Alias template for remove_all_extents template<typename _Tp> using remove_all_extents_t = typename remove_all_extents<_Tp>::type; #endif // Pointer modifications. /// remove_pointer #if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_pointer) template<typename _Tp> struct remove_pointer { using type = __remove_pointer(_Tp); }; #else template<typename _Tp, typename> struct __remove_pointer_helper { using type = _Tp; }; template<typename _Tp, typename _Up> struct __remove_pointer_helper<_Tp, _Up*> { using type = _Up; }; template<typename _Tp> struct remove_pointer : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>> { }; #endif /// add_pointer #if _GLIBCXX_USE_BUILTIN_TRAIT(__add_pointer) template<typename _Tp> struct add_pointer { using type = __add_pointer(_Tp); }; #else template<typename _Tp, typename = void> struct __add_pointer_helper { using type = _Tp; }; template<typename _Tp> struct __add_pointer_helper<_Tp, __void_t<_Tp*>> { using type = _Tp*; }; template<typename _Tp> struct add_pointer : public __add_pointer_helper<_Tp> { }; template<typename _Tp> struct add_pointer<_Tp&> { using type = _Tp*; }; template<typename _Tp> struct add_pointer<_Tp&&> { using type = _Tp*; }; #endif #if __cplusplus > 201103L /// Alias template for remove_pointer template<typename _Tp> using remove_pointer_t = typename remove_pointer<_Tp>::type; /// Alias template for add_pointer template<typename _Tp> using add_pointer_t = typename add_pointer<_Tp>::type; #endif /// @cond undocumented // Aligned to maximum fundamental alignment struct __attribute__((__aligned__)) __aligned_storage_max_align_t { }; constexpr size_t __aligned_storage_default_alignment([[__maybe_unused__]] size_t __len) { #if _GLIBCXX_INLINE_VERSION using _Max_align = integral_constant<size_t, alignof(__aligned_storage_max_align_t)>; return __len > (_Max_align::value / 2) ? _Max_align::value # if _GLIBCXX_USE_BUILTIN_TRAIT(__builtin_clzg) : 1 << (__SIZE_WIDTH__ - __builtin_clzg(__len - 1u)); # else : 1 << (__LLONG_WIDTH__ - __builtin_clzll(__len - 1ull)); # endif #else // Returning a fixed value is incorrect, but kept for ABI compatibility. // XXX GLIBCXX_ABI Deprecated return alignof(__aligned_storage_max_align_t); #endif } /// @endcond /** * @brief Aligned storage * * The member typedef `type` is be a POD type suitable for use as * uninitialized storage for any object whose size is at most `_Len` * and whose alignment is a divisor of `_Align`. * * It is important to use the nested `type` as uninitialized storage, * not the `std::aligned_storage` type itself which is an empty class * with 1-byte alignment. So this is correct: * * `typename std::aligned_storage<sizeof(X), alignof(X)>::type m_xobj;` * * This is wrong: * * `std::aligned_storage<sizeof(X), alignof(X)> m_xobj;` * * In C++14 and later `std::aligned_storage_t<sizeof(X), alignof(X)>` * can be used to refer to the `type` member typedef. * * The default value of _Align is supposed to be the most stringent * fundamental alignment requirement for any C++ object type whose size * is no greater than `_Len` (see [basic.align] in the C++ standard). * * @bug In this implementation the default value for _Align is always the * maximum fundamental alignment, i.e. `alignof(max_align_t)`, which is * incorrect. It should be an alignment value no greater than `_Len`. * * @deprecated Deprecated in C++23. Uses can be replaced by an * array `std::byte[_Len]` declared with `alignas(_Align)`. */ template<size_t _Len, size_t _Align = __aligned_storage_default_alignment(_Len)> struct _GLIBCXX23_DEPRECATED aligned_storage { struct type { alignas(_Align) unsigned char __data[_Len]; }; }; template <typename... _Types> struct __strictest_alignment { static const size_t _S_alignment = 0; static const size_t _S_size = 0; }; template <typename _Tp, typename... _Types> struct __strictest_alignment<_Tp, _Types...> { static const size_t _S_alignment = alignof(_Tp) > __strictest_alignment<_Types...>::_S_alignment ? alignof(_Tp) : __strictest_alignment<_Types...>::_S_alignment; static const size_t _S_size = sizeof(_Tp) > __strictest_alignment<_Types...>::_S_size ? sizeof(_Tp) : __strictest_alignment<_Types...>::_S_size; }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" /** * @brief Provide aligned storage for types. * * [meta.trans.other] * * Provides aligned storage for any of the provided types of at * least size _Len. * * @see aligned_storage * * @deprecated Deprecated in C++23. */ template <size_t _Len, typename... _Types> struct _GLIBCXX23_DEPRECATED aligned_union { private: static_assert(sizeof...(_Types) != 0, "At least one type is required"); using __strictest = __strictest_alignment<_Types...>; static const size_t _S_len = _Len > __strictest::_S_size ? _Len : __strictest::_S_size; public: /// The value of the strictest alignment of _Types. static const size_t alignment_value = __strictest::_S_alignment; /// The storage. using type = typename aligned_storage<_S_len, alignment_value>::type; }; template <size_t _Len, typename... _Types> const size_t aligned_union<_Len, _Types...>::alignment_value; #pragma GCC diagnostic pop /// @cond undocumented #if _GLIBCXX_USE_BUILTIN_TRAIT(__decay) template<typename _Tp> struct decay { using type = __decay(_Tp); }; #else // Decay trait for arrays and functions, used for perfect forwarding // in make_pair, make_tuple, etc. template<typename _Up> struct __decay_selector : __conditional_t<is_const<const _Up>::value, // false for functions remove_cv<_Up>, // N.B. DR 705. add_pointer<_Up>> // function decays to pointer { }; template<typename _Up, size_t _Nm> struct __decay_selector<_Up[_Nm]> { using type = _Up*; }; template<typename _Up> struct __decay_selector<_Up[]> { using type = _Up*; }; /// @endcond /// decay template<typename _Tp> struct decay { using type = typename __decay_selector<_Tp>::type; }; template<typename _Tp> struct decay<_Tp&> { using type = typename __decay_selector<_Tp>::type; }; template<typename _Tp> struct decay<_Tp&&> { using type = typename __decay_selector<_Tp>::type; }; #endif /// @cond undocumented // Helper which adds a reference to a type when given a reference_wrapper template<typename _Tp> struct __strip_reference_wrapper { using __type = _Tp; }; template<typename _Tp> struct __strip_reference_wrapper<reference_wrapper<_Tp> > { using __type = _Tp&; }; // __decay_t (std::decay_t for C++11). template<typename _Tp> using __decay_t = typename decay<_Tp>::type; template<typename _Tp> using __decay_and_strip = __strip_reference_wrapper<__decay_t<_Tp>>; /// @endcond /// @cond undocumented // Helper for SFINAE constraints template<typename... _Cond> using _Require = __enable_if_t<__and_<_Cond...>::value>; // __remove_cvref_t (std::remove_cvref_t for C++11). template<typename _Tp> using __remove_cvref_t = typename remove_cv<typename remove_reference<_Tp>::type>::type; /// @endcond // Primary template. /// Define a member typedef @c type to one of two argument types. template<bool _Cond, typename _Iftrue, typename _Iffalse> struct conditional { using type = _Iftrue; }; // Partial specialization for false. template<typename _Iftrue, typename _Iffalse> struct conditional<false, _Iftrue, _Iffalse> { using type = _Iffalse; }; /// common_type template<typename... _Tp> struct common_type; // Sfinae-friendly common_type implementation: /// @cond undocumented // For several sfinae-friendly trait implementations we transport both the // result information (as the member type) and the failure information (no // member type). This is very similar to std::enable_if, but we cannot use // that, because we need to derive from them as an implementation detail. template<typename _Tp> struct __success_type { using type = _Tp; }; struct __failure_type { }; struct __do_common_type_impl { template<typename _Tp, typename _Up> using __cond_t = decltype(true ? std::declval<_Tp>() : std::declval<_Up>()); // if decay_t<decltype(false ? declval<D1>() : declval<D2>())> // denotes a valid type, let C denote that type. template<typename _Tp, typename _Up> static __success_type<__decay_t<__cond_t<_Tp, _Up>>> _S_test(int); #if __cplusplus > 201703L // Otherwise, if COND-RES(CREF(D1), CREF(D2)) denotes a type, // let C denote the type decay_t<COND-RES(CREF(D1), CREF(D2))>. template<typename _Tp, typename _Up> static __success_type<__remove_cvref_t<__cond_t<const _Tp&, const _Up&>>> _S_test_2(int); #endif template<typename, typename> static __failure_type _S_test_2(...); template<typename _Tp, typename _Up> static decltype(_S_test_2<_Tp, _Up>(0)) _S_test(...); }; // If sizeof...(T) is zero, there shall be no member type. template<> struct common_type<> { }; // If sizeof...(T) is one, the same type, if any, as common_type_t<T0, T0>. template<typename _Tp0> struct common_type<_Tp0> : public common_type<_Tp0, _Tp0> { }; // If sizeof...(T) is two, ... template<typename _Tp1, typename _Tp2, typename _Dp1 = __decay_t<_Tp1>, typename _Dp2 = __decay_t<_Tp2>> struct __common_type_impl { // If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false, // let C denote the same type, if any, as common_type_t<D1, D2>. using type = common_type<_Dp1, _Dp2>; }; template<typename _Tp1, typename _Tp2> struct __common_type_impl<_Tp1, _Tp2, _Tp1, _Tp2> : private __do_common_type_impl { // Otherwise, if decay_t<decltype(false ? declval<D1>() : declval<D2>())> // denotes a valid type, let C denote that type. using type = decltype(_S_test<_Tp1, _Tp2>(0)); }; // If sizeof...(T) is two, ... template<typename _Tp1, typename _Tp2> struct common_type<_Tp1, _Tp2> : public __common_type_impl<_Tp1, _Tp2>::type { }; template<typename...> struct __common_type_pack { }; template<typename, typename, typename = void> struct __common_type_fold; // If sizeof...(T) is greater than two, ... template<typename _Tp1, typename _Tp2, typename... _Rp> struct common_type<_Tp1, _Tp2, _Rp...> : public __common_type_fold<common_type<_Tp1, _Tp2>, __common_type_pack<_Rp...>> { }; // Let C denote the same type, if any, as common_type_t<T1, T2>. // If there is such a type C, type shall denote the same type, if any, // as common_type_t<C, R...>. template<typename _CTp, typename... _Rp> struct __common_type_fold<_CTp, __common_type_pack<_Rp...>, __void_t<typename _CTp::type>> : public common_type<typename _CTp::type, _Rp...> { }; // Otherwise, there shall be no member type. template<typename _CTp, typename _Rp> struct __common_type_fold<_CTp, _Rp, void> { }; template<typename _Tp, bool = __is_enum(_Tp)> struct __underlying_type_impl { using type = __underlying_type(_Tp); }; template<typename _Tp> struct __underlying_type_impl<_Tp, false> { }; /// @endcond /// The underlying type of an enum. template<typename _Tp> struct underlying_type : public __underlying_type_impl<_Tp> { }; /// @cond undocumented template<typename _Tp> struct __declval_protector { static const bool __stop = false; }; /// @endcond /** Utility to simplify expressions used in unevaluated operands * @since C++11 * @ingroup utilities */ template<typename _Tp> auto declval() noexcept -> decltype(__declval<_Tp>(0)) { static_assert(__declval_protector<_Tp>::__stop, "declval() must not be used!"); return __declval<_Tp>(0); } /// result_of template<typename _Signature> struct result_of; // Sfinae-friendly result_of implementation: /// @cond undocumented struct __invoke_memfun_ref { }; struct __invoke_memfun_deref { }; struct __invoke_memobj_ref { }; struct __invoke_memobj_deref { }; struct __invoke_other { }; // Associate a tag type with a specialization of __success_type. template<typename _Tp, typename _Tag> struct __result_of_success : __success_type<_Tp> { using __invoke_type = _Tag; }; // [func.require] paragraph 1 bullet 1: struct __result_of_memfun_ref_impl { template<typename _Fp, typename _Tp1, typename... _Args> static __result_of_success<decltype( (std::declval<_Tp1>().*std::declval<_Fp>())(std::declval<_Args>()...) ), __invoke_memfun_ref> _S_test(int); template<typename...> static __failure_type _S_test(...); }; template<typename _MemPtr, typename _Arg, typename... _Args> struct __result_of_memfun_ref : private __result_of_memfun_ref_impl { using type = decltype(_S_test<_MemPtr, _Arg, _Args...>(0)); }; // [func.require] paragraph 1 bullet 2: struct __result_of_memfun_deref_impl { template<typename _Fp, typename _Tp1, typename... _Args> static __result_of_success<decltype( ((*std::declval<_Tp1>()).*std::declval<_Fp>())(std::declval<_Args>()...) ), __invoke_memfun_deref> _S_test(int); template<typename...> static __failure_type _S_test(...); }; template<typename _MemPtr, typename _Arg, typename... _Args> struct __result_of_memfun_deref : private __result_of_memfun_deref_impl { using type = decltype(_S_test<_MemPtr, _Arg, _Args...>(0)); }; // [func.require] paragraph 1 bullet 3: struct __result_of_memobj_ref_impl { template<typename _Fp, typename _Tp1> static __result_of_success<decltype( std::declval<_Tp1>().*std::declval<_Fp>() ), __invoke_memobj_ref> _S_test(int); template<typename, typename> static __failure_type _S_test(...); }; template<typename _MemPtr, typename _Arg> struct __result_of_memobj_ref : private __result_of_memobj_ref_impl { using type = decltype(_S_test<_MemPtr, _Arg>(0)); }; // [func.require] paragraph 1 bullet 4: struct __result_of_memobj_deref_impl { template<typename _Fp, typename _Tp1> static __result_of_success<decltype( (*std::declval<_Tp1>()).*std::declval<_Fp>() ), __invoke_memobj_deref> _S_test(int); template<typename, typename> static __failure_type _S_test(...); }; template<typename _MemPtr, typename _Arg> struct __result_of_memobj_deref : private __result_of_memobj_deref_impl { using type = decltype(_S_test<_MemPtr, _Arg>(0)); }; template<typename _MemPtr, typename _Arg> struct __result_of_memobj; template<typename _Res, typename _Class, typename _Arg> struct __result_of_memobj<_Res _Class::*, _Arg> { using _Argval = __remove_cvref_t<_Arg>; using _MemPtr = _Res _Class::*; using type = typename __conditional_t<__or_<is_same<_Argval, _Class>, is_base_of<_Class, _Argval>>::value, __result_of_memobj_ref<_MemPtr, _Arg>, __result_of_memobj_deref<_MemPtr, _Arg> >::type; }; template<typename _MemPtr, typename _Arg, typename... _Args> struct __result_of_memfun; template<typename _Res, typename _Class, typename _Arg, typename... _Args> struct __result_of_memfun<_Res _Class::*, _Arg, _Args...> { using _Argval = typename remove_reference<_Arg>::type; using _MemPtr = _Res _Class::*; using type = typename __conditional_t<is_base_of<_Class, _Argval>::value, __result_of_memfun_ref<_MemPtr, _Arg, _Args...>, __result_of_memfun_deref<_MemPtr, _Arg, _Args...> >::type; }; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2219. INVOKE-ing a pointer to member with a reference_wrapper // as the object expression // Used by result_of, invoke etc. to unwrap a reference_wrapper. template<typename _Tp, typename _Up = __remove_cvref_t<_Tp>> struct __inv_unwrap { using type = _Tp; }; template<typename _Tp, typename _Up> struct __inv_unwrap<_Tp, reference_wrapper<_Up>> { using type = _Up&; }; template<bool, bool, typename _Functor, typename... _ArgTypes> struct __result_of_impl { using type = __failure_type; }; template<typename _MemPtr, typename _Arg> struct __result_of_impl<true, false, _MemPtr, _Arg> : public __result_of_memobj<__decay_t<_MemPtr>, typename __inv_unwrap<_Arg>::type> { }; template<typename _MemPtr, typename _Arg, typename... _Args> struct __result_of_impl<false, true, _MemPtr, _Arg, _Args...> : public __result_of_memfun<__decay_t<_MemPtr>, typename __inv_unwrap<_Arg>::type, _Args...> { }; // [func.require] paragraph 1 bullet 5: struct __result_of_other_impl { template<typename _Fn, typename... _Args> static __result_of_success<decltype( std::declval<_Fn>()(std::declval<_Args>()...) ), __invoke_other> _S_test(int); template<typename...> static __failure_type _S_test(...); }; template<typename _Functor, typename... _ArgTypes> struct __result_of_impl<false, false, _Functor, _ArgTypes...> : private __result_of_other_impl { using type = decltype(_S_test<_Functor, _ArgTypes...>(0)); }; // __invoke_result (std::invoke_result for C++11) template<typename _Functor, typename... _ArgTypes> struct __invoke_result : public __result_of_impl< is_member_object_pointer< typename remove_reference<_Functor>::type >::value, is_member_function_pointer< typename remove_reference<_Functor>::type >::value, _Functor, _ArgTypes... >::type { }; // __invoke_result_t (std::invoke_result_t for C++11) template<typename _Fn, typename... _Args> using __invoke_result_t = typename __invoke_result<_Fn, _Args...>::type; /// @endcond template<typename _Functor, typename... _ArgTypes> struct result_of<_Functor(_ArgTypes...)> : public __invoke_result<_Functor, _ArgTypes...> { } _GLIBCXX17_DEPRECATED_SUGGEST("std::invoke_result"); #if __cplusplus >= 201402L #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" /// Alias template for aligned_storage template<size_t _Len, size_t _Align = __aligned_storage_default_alignment(_Len)> using aligned_storage_t _GLIBCXX23_DEPRECATED = typename aligned_storage<_Len, _Align>::type; template <size_t _Len, typename... _Types> using aligned_union_t _GLIBCXX23_DEPRECATED = typename aligned_union<_Len, _Types...>::type; #pragma GCC diagnostic pop /// Alias template for decay template<typename _Tp> using decay_t = typename decay<_Tp>::type; /// Alias template for enable_if template<bool _Cond, typename _Tp = void> using enable_if_t = typename enable_if<_Cond, _Tp>::type; /// Alias template for conditional template<bool _Cond, typename _Iftrue, typename _Iffalse> using conditional_t = typename conditional<_Cond, _Iftrue, _Iffalse>::type; /// Alias template for common_type template<typename... _Tp> using common_type_t = typename common_type<_Tp...>::type; /// Alias template for underlying_type template<typename _Tp> using underlying_type_t = typename underlying_type<_Tp>::type; /// Alias template for result_of template<typename _Tp> using result_of_t = typename result_of<_Tp>::type; #endif // C++14 #ifdef __cpp_lib_void_t // C++ >= 17 || GNU++ >= 11 /// A metafunction that always yields void, used for detecting valid types. template<typename...> using void_t = void; #endif /// @cond undocumented // Detection idiom. // Detect whether _Op<_Args...> is a valid type, use default _Def if not. #if __cpp_concepts // Implementation of the detection idiom (negative case). template<typename _Def, template<typename...> class _Op, typename... _Args> struct __detected_or { using type = _Def; using __is_detected = false_type; }; // Implementation of the detection idiom (positive case). template<typename _Def, template<typename...> class _Op, typename... _Args> requires requires { typename _Op<_Args...>; } struct __detected_or<_Def, _Op, _Args...> { using type = _Op<_Args...>; using __is_detected = true_type; }; #else /// Implementation of the detection idiom (negative case). template<typename _Default, typename _AlwaysVoid, template<typename...> class _Op, typename... _Args> struct __detector { using type = _Default; using __is_detected = false_type; }; /// Implementation of the detection idiom (positive case). template<typename _Default, template<typename...> class _Op, typename... _Args> struct __detector<_Default, __void_t<_Op<_Args...>>, _Op, _Args...> { using type = _Op<_Args...>; using __is_detected = true_type; }; template<typename _Default, template<typename...> class _Op, typename... _Args> using __detected_or = __detector<_Default, void, _Op, _Args...>; #endif // __cpp_concepts // _Op<_Args...> if that is a valid type, otherwise _Default. template<typename _Default, template<typename...> class _Op, typename... _Args> using __detected_or_t = typename __detected_or<_Default, _Op, _Args...>::type; /** * Use SFINAE to determine if the type _Tp has a publicly-accessible * member type _NTYPE. */ #define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE) \ template<typename _Tp, typename = __void_t<>> \ struct __has_##_NTYPE \ : false_type \ { }; \ template<typename _Tp> \ struct __has_##_NTYPE<_Tp, __void_t<typename _Tp::_NTYPE>> \ : true_type \ { }; template <typename _Tp> struct __is_swappable; template <typename _Tp> struct __is_nothrow_swappable; template<typename> struct __is_tuple_like_impl : false_type { }; // Internal type trait that allows us to sfinae-protect tuple_cat. template<typename _Tp> struct __is_tuple_like : public __is_tuple_like_impl<__remove_cvref_t<_Tp>>::type { }; /// @endcond template<typename _Tp> _GLIBCXX20_CONSTEXPR inline _Require<__not_<__is_tuple_like<_Tp>>, is_move_constructible<_Tp>, is_move_assignable<_Tp>> swap(_Tp&, _Tp&) noexcept(__and_<is_nothrow_move_constructible<_Tp>, is_nothrow_move_assignable<_Tp>>::value); template<typename _Tp, size_t _Nm> _GLIBCXX20_CONSTEXPR inline __enable_if_t<__is_swappable<_Tp>::value> swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) noexcept(__is_nothrow_swappable<_Tp>::value); /// @cond undocumented namespace __swappable_details { using std::swap; struct __do_is_swappable_impl { template<typename _Tp, typename = decltype(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))> static true_type __test(int); template<typename> static false_type __test(...); }; struct __do_is_nothrow_swappable_impl { template<typename _Tp> static __bool_constant< noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())) > __test(int); template<typename> static false_type __test(...); }; } // namespace __swappable_details template<typename _Tp> struct __is_swappable_impl : public __swappable_details::__do_is_swappable_impl { using type = decltype(__test<_Tp>(0)); }; template<typename _Tp> struct __is_nothrow_swappable_impl : public __swappable_details::__do_is_nothrow_swappable_impl { using type = decltype(__test<_Tp>(0)); }; template<typename _Tp> struct __is_swappable : public __is_swappable_impl<_Tp>::type { }; template<typename _Tp> struct __is_nothrow_swappable : public __is_nothrow_swappable_impl<_Tp>::type { }; /// @endcond #ifdef __cpp_lib_is_swappable // C++ >= 17 || GNU++ >= 11 /// Metafunctions used for detecting swappable types: p0185r1 /// is_swappable template<typename _Tp> struct is_swappable : public __is_swappable_impl<_Tp>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; /// is_nothrow_swappable template<typename _Tp> struct is_nothrow_swappable : public __is_nothrow_swappable_impl<_Tp>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; #if __cplusplus >= 201402L /// is_swappable_v template<typename _Tp> _GLIBCXX17_INLINE constexpr bool is_swappable_v = is_swappable<_Tp>::value; /// is_nothrow_swappable_v template<typename _Tp> _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_v = is_nothrow_swappable<_Tp>::value; #endif // __cplusplus >= 201402L /// @cond undocumented namespace __swappable_with_details { using std::swap; struct __do_is_swappable_with_impl { template<typename _Tp, typename _Up, typename = decltype(swap(std::declval<_Tp>(), std::declval<_Up>())), typename = decltype(swap(std::declval<_Up>(), std::declval<_Tp>()))> static true_type __test(int); template<typename, typename> static false_type __test(...); }; struct __do_is_nothrow_swappable_with_impl { template<typename _Tp, typename _Up> static __bool_constant< noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())) && noexcept(swap(std::declval<_Up>(), std::declval<_Tp>())) > __test(int); template<typename, typename> static false_type __test(...); }; } // namespace __swappable_with_details template<typename _Tp, typename _Up> struct __is_swappable_with_impl : public __swappable_with_details::__do_is_swappable_with_impl { using type = decltype(__test<_Tp, _Up>(0)); }; // Optimization for the homogenous lvalue case, not required: template<typename _Tp> struct __is_swappable_with_impl<_Tp&, _Tp&> : public __swappable_details::__do_is_swappable_impl { using type = decltype(__test<_Tp&>(0)); }; template<typename _Tp, typename _Up> struct __is_nothrow_swappable_with_impl : public __swappable_with_details::__do_is_nothrow_swappable_with_impl { using type = decltype(__test<_Tp, _Up>(0)); }; // Optimization for the homogenous lvalue case, not required: template<typename _Tp> struct __is_nothrow_swappable_with_impl<_Tp&, _Tp&> : public __swappable_details::__do_is_nothrow_swappable_impl { using type = decltype(__test<_Tp&>(0)); }; /// @endcond /// is_swappable_with template<typename _Tp, typename _Up> struct is_swappable_with : public __is_swappable_with_impl<_Tp, _Up>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "first template argument must be a complete class or an unbounded array"); static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}), "second template argument must be a complete class or an unbounded array"); }; /// is_nothrow_swappable_with template<typename _Tp, typename _Up> struct is_nothrow_swappable_with : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "first template argument must be a complete class or an unbounded array"); static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}), "second template argument must be a complete class or an unbounded array"); }; #if __cplusplus >= 201402L /// is_swappable_with_v template<typename _Tp, typename _Up> _GLIBCXX17_INLINE constexpr bool is_swappable_with_v = is_swappable_with<_Tp, _Up>::value; /// is_nothrow_swappable_with_v template<typename _Tp, typename _Up> _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_with_v = is_nothrow_swappable_with<_Tp, _Up>::value; #endif // __cplusplus >= 201402L #endif // __cpp_lib_is_swappable /// @cond undocumented // __is_invocable (std::is_invocable for C++11) // The primary template is used for invalid INVOKE expressions. template<typename _Result, typename _Ret, bool = is_void<_Ret>::value, typename = void> struct __is_invocable_impl : false_type { using __nothrow_conv = false_type; // For is_nothrow_invocable_r }; // Used for valid INVOKE and INVOKE<void> expressions. template<typename _Result, typename _Ret> struct __is_invocable_impl<_Result, _Ret, /* is_void<_Ret> = */ true, __void_t<typename _Result::type>> : true_type { using __nothrow_conv = true_type; // For is_nothrow_invocable_r }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" // Used for INVOKE<R> expressions to check the implicit conversion to R. template<typename _Result, typename _Ret> struct __is_invocable_impl<_Result, _Ret, /* is_void<_Ret> = */ false, __void_t<typename _Result::type>> { private: // The type of the INVOKE expression. using _Res_t = typename _Result::type; // Unlike declval, this doesn't add_rvalue_reference, so it respects // guaranteed copy elision. static _Res_t _S_get() noexcept; // Used to check if _Res_t can implicitly convert to _Tp. template<typename _Tp> static void _S_conv(__type_identity_t<_Tp>) noexcept; // This overload is viable if INVOKE(f, args...) can convert to _Tp. template<typename _Tp, bool _Nothrow = noexcept(_S_conv<_Tp>(_S_get())), typename = decltype(_S_conv<_Tp>(_S_get())), #if __has_builtin(__reference_converts_from_temporary) bool _Dangle = __reference_converts_from_temporary(_Tp, _Res_t) #else bool _Dangle = false #endif > static __bool_constant<_Nothrow && !_Dangle> _S_test(int); template<typename _Tp, bool = false> static false_type _S_test(...); public: // For is_invocable_r using type = decltype(_S_test<_Ret, /* Nothrow = */ true>(1)); // For is_nothrow_invocable_r using __nothrow_conv = decltype(_S_test<_Ret>(1)); }; #pragma GCC diagnostic pop template<typename _Fn, typename... _ArgTypes> struct __is_invocable #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_invocable) : __bool_constant<__is_invocable(_Fn, _ArgTypes...)> #else : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type #endif { }; template<typename _Fn, typename _Tp, typename... _Args> constexpr bool __call_is_nt(__invoke_memfun_ref) { using _Up = typename __inv_unwrap<_Tp>::type; return noexcept((std::declval<_Up>().*std::declval<_Fn>())( std::declval<_Args>()...)); } template<typename _Fn, typename _Tp, typename... _Args> constexpr bool __call_is_nt(__invoke_memfun_deref) { return noexcept(((*std::declval<_Tp>()).*std::declval<_Fn>())( std::declval<_Args>()...)); } template<typename _Fn, typename _Tp> constexpr bool __call_is_nt(__invoke_memobj_ref) { using _Up = typename __inv_unwrap<_Tp>::type; return noexcept(std::declval<_Up>().*std::declval<_Fn>()); } template<typename _Fn, typename _Tp> constexpr bool __call_is_nt(__invoke_memobj_deref) { return noexcept((*std::declval<_Tp>()).*std::declval<_Fn>()); } template<typename _Fn, typename... _Args> constexpr bool __call_is_nt(__invoke_other) { return noexcept(std::declval<_Fn>()(std::declval<_Args>()...)); } template<typename _Result, typename _Fn, typename... _Args> struct __call_is_nothrow : __bool_constant< std::__call_is_nt<_Fn, _Args...>(typename _Result::__invoke_type{}) > { }; template<typename _Fn, typename... _Args> using __call_is_nothrow_ = __call_is_nothrow<__invoke_result<_Fn, _Args...>, _Fn, _Args...>; // __is_nothrow_invocable (std::is_nothrow_invocable for C++11) template<typename _Fn, typename... _Args> struct __is_nothrow_invocable #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_invocable) : __bool_constant<__is_nothrow_invocable(_Fn, _Args...)> #else : __and_<__is_invocable<_Fn, _Args...>, __call_is_nothrow_<_Fn, _Args...>>::type #endif { }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" struct __nonesuchbase {}; struct __nonesuch : private __nonesuchbase { ~__nonesuch() = delete; __nonesuch(__nonesuch const&) = delete; void operator=(__nonesuch const&) = delete; }; #pragma GCC diagnostic pop /// @endcond #ifdef __cpp_lib_is_invocable // C++ >= 17 /// std::invoke_result template<typename _Functor, typename... _ArgTypes> struct invoke_result : public __invoke_result<_Functor, _ArgTypes...> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Functor>{}), "_Functor must be a complete class or an unbounded array"); static_assert((std::__is_complete_or_unbounded( __type_identity<_ArgTypes>{}) && ...), "each argument type must be a complete class or an unbounded array"); }; /// std::invoke_result_t template<typename _Fn, typename... _Args> using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; /// std::is_invocable template<typename _Fn, typename... _ArgTypes> struct is_invocable #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_invocable) : public __bool_constant<__is_invocable(_Fn, _ArgTypes...)> #else : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type #endif { static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), "_Fn must be a complete class or an unbounded array"); static_assert((std::__is_complete_or_unbounded( __type_identity<_ArgTypes>{}) && ...), "each argument type must be a complete class or an unbounded array"); }; /// std::is_invocable_r template<typename _Ret, typename _Fn, typename... _ArgTypes> struct is_invocable_r : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), "_Fn must be a complete class or an unbounded array"); static_assert((std::__is_complete_or_unbounded( __type_identity<_ArgTypes>{}) && ...), "each argument type must be a complete class or an unbounded array"); static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}), "_Ret must be a complete class or an unbounded array"); }; /// std::is_nothrow_invocable template<typename _Fn, typename... _ArgTypes> struct is_nothrow_invocable #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_invocable) : public __bool_constant<__is_nothrow_invocable(_Fn, _ArgTypes...)> #else : __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>, __call_is_nothrow_<_Fn, _ArgTypes...>>::type #endif { static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), "_Fn must be a complete class or an unbounded array"); static_assert((std::__is_complete_or_unbounded( __type_identity<_ArgTypes>{}) && ...), "each argument type must be a complete class or an unbounded array"); }; /// @cond undocumented // This checks that the INVOKE<R> expression is well-formed and that the // conversion to R does not throw. It does *not* check whether the INVOKE // expression itself can throw. That is done by __call_is_nothrow_ instead. template<typename _Result, typename _Ret> using __is_nt_invocable_impl = typename __is_invocable_impl<_Result, _Ret>::__nothrow_conv; /// @endcond /// std::is_nothrow_invocable_r template<typename _Ret, typename _Fn, typename... _ArgTypes> struct is_nothrow_invocable_r : __and_<__is_nt_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>, __call_is_nothrow_<_Fn, _ArgTypes...>>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), "_Fn must be a complete class or an unbounded array"); static_assert((std::__is_complete_or_unbounded( __type_identity<_ArgTypes>{}) && ...), "each argument type must be a complete class or an unbounded array"); static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}), "_Ret must be a complete class or an unbounded array"); }; #endif // __cpp_lib_is_invocable #if __cpp_lib_type_trait_variable_templates // C++ >= 17 /** * @defgroup variable_templates Variable templates for type traits * @ingroup metaprogramming * * Each variable `is_xxx_v<T>` is a boolean constant with the same value * as the `value` member of the corresponding type trait `is_xxx<T>`. * * @since C++17 unless noted otherwise. */ /** * @{ * @ingroup variable_templates */ template <typename _Tp> inline constexpr bool is_void_v = is_void<_Tp>::value; template <typename _Tp> inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value; template <typename _Tp> inline constexpr bool is_integral_v = is_integral<_Tp>::value; template <typename _Tp> inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value; #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_array) template <typename _Tp> inline constexpr bool is_array_v = __is_array(_Tp); #else template <typename _Tp> inline constexpr bool is_array_v = false; template <typename _Tp> inline constexpr bool is_array_v<_Tp[]> = true; template <typename _Tp, size_t _Num> inline constexpr bool is_array_v<_Tp[_Num]> = true; #endif #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_pointer) template <typename _Tp> inline constexpr bool is_pointer_v = __is_pointer(_Tp); #else template <typename _Tp> inline constexpr bool is_pointer_v = false; template <typename _Tp> inline constexpr bool is_pointer_v<_Tp*> = true; template <typename _Tp> inline constexpr bool is_pointer_v<_Tp* const> = true; template <typename _Tp> inline constexpr bool is_pointer_v<_Tp* volatile> = true; template <typename _Tp> inline constexpr bool is_pointer_v<_Tp* const volatile> = true; #endif template <typename _Tp> inline constexpr bool is_lvalue_reference_v = false; template <typename _Tp> inline constexpr bool is_lvalue_reference_v<_Tp&> = true; template <typename _Tp> inline constexpr bool is_rvalue_reference_v = false; template <typename _Tp> inline constexpr bool is_rvalue_reference_v<_Tp&&> = true; #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_object_pointer) template <typename _Tp> inline constexpr bool is_member_object_pointer_v = __is_member_object_pointer(_Tp); #else template <typename _Tp> inline constexpr bool is_member_object_pointer_v = is_member_object_pointer<_Tp>::value; #endif #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer) template <typename _Tp> inline constexpr bool is_member_function_pointer_v = __is_member_function_pointer(_Tp); #else template <typename _Tp> inline constexpr bool is_member_function_pointer_v = is_member_function_pointer<_Tp>::value; #endif template <typename _Tp> inline constexpr bool is_enum_v = __is_enum(_Tp); template <typename _Tp> inline constexpr bool is_union_v = __is_union(_Tp); template <typename _Tp> inline constexpr bool is_class_v = __is_class(_Tp); // is_function_v is defined below, after is_const_v. #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference) template <typename _Tp> inline constexpr bool is_reference_v = __is_reference(_Tp); #else template <typename _Tp> inline constexpr bool is_reference_v = false; template <typename _Tp> inline constexpr bool is_reference_v<_Tp&> = true; template <typename _Tp> inline constexpr bool is_reference_v<_Tp&&> = true; #endif template <typename _Tp> inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value; template <typename _Tp> inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value; #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_object) template <typename _Tp> inline constexpr bool is_object_v = __is_object(_Tp); #else template <typename _Tp> inline constexpr bool is_object_v = is_object<_Tp>::value; #endif template <typename _Tp> inline constexpr bool is_scalar_v = is_scalar<_Tp>::value; template <typename _Tp> inline constexpr bool is_compound_v = !is_fundamental_v<_Tp>; #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer) template <typename _Tp> inline constexpr bool is_member_pointer_v = __is_member_pointer(_Tp); #else template <typename _Tp> inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value; #endif #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_const) template <typename _Tp> inline constexpr bool is_const_v = __is_const(_Tp); #else template <typename _Tp> inline constexpr bool is_const_v = false; template <typename _Tp> inline constexpr bool is_const_v<const _Tp> = true; #endif #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function) template <typename _Tp> inline constexpr bool is_function_v = __is_function(_Tp); #else template <typename _Tp> inline constexpr bool is_function_v = !is_const_v<const _Tp>; template <typename _Tp> inline constexpr bool is_function_v<_Tp&> = false; template <typename _Tp> inline constexpr bool is_function_v<_Tp&&> = false; #endif #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_volatile) template <typename _Tp> inline constexpr bool is_volatile_v = __is_volatile(_Tp); #else template <typename _Tp> inline constexpr bool is_volatile_v = false; template <typename _Tp> inline constexpr bool is_volatile_v<volatile _Tp> = true; #endif template <typename _Tp> _GLIBCXX26_DEPRECATED_SUGGEST("is_trivially_default_constructible_v && is_trivially_copyable_v") inline constexpr bool is_trivial_v = __is_trivial(_Tp); template <typename _Tp> inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Tp); template <typename _Tp> inline constexpr bool is_standard_layout_v = __is_standard_layout(_Tp); template <typename _Tp> _GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout_v && is_trivial_v") inline constexpr bool is_pod_v = __is_pod(_Tp); template <typename _Tp> _GLIBCXX17_DEPRECATED inline constexpr bool is_literal_type_v = __is_literal_type(_Tp); template <typename _Tp> inline constexpr bool is_empty_v = __is_empty(_Tp); template <typename _Tp> inline constexpr bool is_polymorphic_v = __is_polymorphic(_Tp); template <typename _Tp> inline constexpr bool is_abstract_v = __is_abstract(_Tp); template <typename _Tp> inline constexpr bool is_final_v = __is_final(_Tp); template <typename _Tp> inline constexpr bool is_signed_v = is_signed<_Tp>::value; template <typename _Tp> inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value; template <typename _Tp, typename... _Args> inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...); template <typename _Tp> inline constexpr bool is_default_constructible_v = __is_constructible(_Tp); template <typename _Tp> inline constexpr bool is_copy_constructible_v = __is_constructible(_Tp, __add_lval_ref_t<const _Tp>); template <typename _Tp> inline constexpr bool is_move_constructible_v = __is_constructible(_Tp, __add_rval_ref_t<_Tp>); template <typename _Tp, typename _Up> inline constexpr bool is_assignable_v = __is_assignable(_Tp, _Up); template <typename _Tp> inline constexpr bool is_copy_assignable_v = __is_assignable(__add_lval_ref_t<_Tp>, __add_lval_ref_t<const _Tp>); template <typename _Tp> inline constexpr bool is_move_assignable_v = __is_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_destructible) template <typename _Tp> inline constexpr bool is_destructible_v = __is_destructible(_Tp); #else template <typename _Tp> inline constexpr bool is_destructible_v = is_destructible<_Tp>::value; #endif template <typename _Tp, typename... _Args> inline constexpr bool is_trivially_constructible_v = __is_trivially_constructible(_Tp, _Args...); template <typename _Tp> inline constexpr bool is_trivially_default_constructible_v = __is_trivially_constructible(_Tp); template <typename _Tp> inline constexpr bool is_trivially_copy_constructible_v = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>); template <typename _Tp> inline constexpr bool is_trivially_move_constructible_v = __is_trivially_constructible(_Tp, __add_rval_ref_t<_Tp>); template <typename _Tp, typename _Up> inline constexpr bool is_trivially_assignable_v = __is_trivially_assignable(_Tp, _Up); template <typename _Tp> inline constexpr bool is_trivially_copy_assignable_v = __is_trivially_assignable(__add_lval_ref_t<_Tp>, __add_lval_ref_t<const _Tp>); template <typename _Tp> inline constexpr bool is_trivially_move_assignable_v = __is_trivially_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_trivially_destructible) template <typename _Tp> inline constexpr bool is_trivially_destructible_v = __is_trivially_destructible(_Tp); #elif __cpp_concepts template <typename _Tp> inline constexpr bool is_trivially_destructible_v = false; template <typename _Tp> requires (!is_reference_v<_Tp>) && requires (_Tp& __t) { __t.~_Tp(); } inline constexpr bool is_trivially_destructible_v<_Tp> = __has_trivial_destructor(_Tp); template <typename _Tp> inline constexpr bool is_trivially_destructible_v<_Tp&> = true; template <typename _Tp> inline constexpr bool is_trivially_destructible_v<_Tp&&> = true; template <typename _Tp, size_t _Nm> inline constexpr bool is_trivially_destructible_v<_Tp[_Nm]> = is_trivially_destructible_v<_Tp>; #else template <typename _Tp> inline constexpr bool is_trivially_destructible_v = is_trivially_destructible<_Tp>::value; #endif template <typename _Tp, typename... _Args> inline constexpr bool is_nothrow_constructible_v = __is_nothrow_constructible(_Tp, _Args...); template <typename _Tp> inline constexpr bool is_nothrow_default_constructible_v = __is_nothrow_constructible(_Tp); template <typename _Tp> inline constexpr bool is_nothrow_copy_constructible_v = __is_nothrow_constructible(_Tp, __add_lval_ref_t<const _Tp>); template <typename _Tp> inline constexpr bool is_nothrow_move_constructible_v = __is_nothrow_constructible(_Tp, __add_rval_ref_t<_Tp>); template <typename _Tp, typename _Up> inline constexpr bool is_nothrow_assignable_v = __is_nothrow_assignable(_Tp, _Up); template <typename _Tp> inline constexpr bool is_nothrow_copy_assignable_v = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, __add_lval_ref_t<const _Tp>); template <typename _Tp> inline constexpr bool is_nothrow_move_assignable_v = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_destructible) template <typename _Tp> inline constexpr bool is_nothrow_destructible_v = __is_nothrow_destructible(_Tp); #else template <typename _Tp> inline constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<_Tp>::value; #endif template <typename _Tp> inline constexpr bool has_virtual_destructor_v = __has_virtual_destructor(_Tp); template <typename _Tp> inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value; #if _GLIBCXX_USE_BUILTIN_TRAIT(__array_rank) \ && (!defined(__clang__) || __clang_major__ >= 20) // PR118559 template <typename _Tp> inline constexpr size_t rank_v = __array_rank(_Tp); #else template <typename _Tp> inline constexpr size_t rank_v = 0; template <typename _Tp, size_t _Size> inline constexpr size_t rank_v<_Tp[_Size]> = 1 + rank_v<_Tp>; template <typename _Tp> inline constexpr size_t rank_v<_Tp[]> = 1 + rank_v<_Tp>; #endif template <typename _Tp, unsigned _Idx = 0> inline constexpr size_t extent_v = 0; template <typename _Tp, size_t _Size> inline constexpr size_t extent_v<_Tp[_Size], 0> = _Size; template <typename _Tp, unsigned _Idx, size_t _Size> inline constexpr size_t extent_v<_Tp[_Size], _Idx> = extent_v<_Tp, _Idx - 1>; template <typename _Tp> inline constexpr size_t extent_v<_Tp[], 0> = 0; template <typename _Tp, unsigned _Idx> inline constexpr size_t extent_v<_Tp[], _Idx> = extent_v<_Tp, _Idx - 1>; #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_same) template <typename _Tp, typename _Up> inline constexpr bool is_same_v = __is_same(_Tp, _Up); #else template <typename _Tp, typename _Up> inline constexpr bool is_same_v = false; template <typename _Tp> inline constexpr bool is_same_v<_Tp, _Tp> = true; #endif template <typename _Base, typename _Derived> inline constexpr bool is_base_of_v = __is_base_of(_Base, _Derived); #ifdef __cpp_lib_is_virtual_base_of // C++ >= 26 template <typename _Base, typename _Derived> inline constexpr bool is_virtual_base_of_v = __builtin_is_virtual_base_of(_Base, _Derived); #endif #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_convertible) template <typename _From, typename _To> inline constexpr bool is_convertible_v = __is_convertible(_From, _To); #else template <typename _From, typename _To> inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value; #endif template<typename _Fn, typename... _Args> inline constexpr bool is_invocable_v #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_invocable) = __is_invocable(_Fn, _Args...); #else = is_invocable<_Fn, _Args...>::value; #endif template<typename _Fn, typename... _Args> inline constexpr bool is_nothrow_invocable_v #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_invocable) = __is_nothrow_invocable(_Fn, _Args...); #else = is_nothrow_invocable<_Fn, _Args...>::value; #endif template<typename _Ret, typename _Fn, typename... _Args> inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value; template<typename _Ret, typename _Fn, typename... _Args> inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; /// @} #endif // __cpp_lib_type_trait_variable_templates #ifdef __cpp_lib_has_unique_object_representations // C++ >= 17 && HAS_UNIQ_OBJ_REP /// has_unique_object_representations /// @since C++17 template<typename _Tp> struct has_unique_object_representations : bool_constant<__has_unique_object_representations( remove_cv_t<remove_all_extents_t<_Tp>> )> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; # if __cpp_lib_type_trait_variable_templates // C++ >= 17 /// @ingroup variable_templates template<typename _Tp> inline constexpr bool has_unique_object_representations_v = has_unique_object_representations<_Tp>::value; # endif #endif #ifdef __cpp_lib_is_aggregate // C++ >= 17 && builtin_is_aggregate /// is_aggregate - true if the type is an aggregate. /// @since C++17 template<typename _Tp> struct is_aggregate : bool_constant<__is_aggregate(remove_cv_t<_Tp>)> { }; # if __cpp_lib_type_trait_variable_templates // C++ >= 17 /** is_aggregate_v - true if the type is an aggregate. * @ingroup variable_templates * @since C++17 */ template<typename _Tp> inline constexpr bool is_aggregate_v = __is_aggregate(remove_cv_t<_Tp>); # endif #endif /** * Remove references and cv-qualifiers. * @since C++20 * @{ */ #ifdef __cpp_lib_remove_cvref // C++ >= 20 # if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_cvref) template<typename _Tp> struct remove_cvref { using type = __remove_cvref(_Tp); }; # else template<typename _Tp> struct remove_cvref { using type = typename remove_cv<_Tp>::type; }; template<typename _Tp> struct remove_cvref<_Tp&> { using type = typename remove_cv<_Tp>::type; }; template<typename _Tp> struct remove_cvref<_Tp&&> { using type = typename remove_cv<_Tp>::type; }; # endif template<typename _Tp> using remove_cvref_t = typename remove_cvref<_Tp>::type; /// @} #endif // __cpp_lib_remove_cvref #ifdef __cpp_lib_type_identity // C++ >= 20 /** * Identity metafunction. * @since C++20 * @{ */ template<typename _Tp> struct type_identity { using type = _Tp; }; template<typename _Tp> using type_identity_t = typename type_identity<_Tp>::type; /// @} #endif #ifdef __cpp_lib_unwrap_ref // C++ >= 20 /** Unwrap a reference_wrapper * @since C++20 * @{ */ template<typename _Tp> struct unwrap_reference { using type = _Tp; }; template<typename _Tp> struct unwrap_reference<reference_wrapper<_Tp>> { using type = _Tp&; }; template<typename _Tp> using unwrap_reference_t = typename unwrap_reference<_Tp>::type; /// @} /** Decay type and if it's a reference_wrapper, unwrap it * @since C++20 * @{ */ template<typename _Tp> struct unwrap_ref_decay { using type = unwrap_reference_t<decay_t<_Tp>>; }; template<typename _Tp> using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; /// @} #endif // __cpp_lib_unwrap_ref #ifdef __cpp_lib_bounded_array_traits // C++ >= 20 /// True for a type that is an array of known bound. /// @ingroup variable_templates /// @since C++20 # if _GLIBCXX_USE_BUILTIN_TRAIT(__is_bounded_array) template<typename _Tp> inline constexpr bool is_bounded_array_v = __is_bounded_array(_Tp); # else template<typename _Tp> inline constexpr bool is_bounded_array_v = false; template<typename _Tp, size_t _Size> inline constexpr bool is_bounded_array_v<_Tp[_Size]> = true; # endif /// True for a type that is an array of unknown bound. /// @ingroup variable_templates /// @since C++20 # if _GLIBCXX_USE_BUILTIN_TRAIT(__is_unbounded_array) template<typename _Tp> inline constexpr bool is_unbounded_array_v = __is_unbounded_array(_Tp); # else template<typename _Tp> inline constexpr bool is_unbounded_array_v = false; template<typename _Tp> inline constexpr bool is_unbounded_array_v<_Tp[]> = true; # endif /// True for a type that is an array of known bound. /// @since C++20 template<typename _Tp> struct is_bounded_array : public bool_constant<is_bounded_array_v<_Tp>> { }; /// True for a type that is an array of unknown bound. /// @since C++20 template<typename _Tp> struct is_unbounded_array : public bool_constant<is_unbounded_array_v<_Tp>> { }; #endif // __cpp_lib_bounded_array_traits #if __has_builtin(__is_layout_compatible) && __cplusplus >= 202002L /// @since C++20 template<typename _Tp, typename _Up> struct is_layout_compatible : bool_constant<__is_layout_compatible(_Tp, _Up)> { }; /// @ingroup variable_templates /// @since C++20 template<typename _Tp, typename _Up> constexpr bool is_layout_compatible_v = __is_layout_compatible(_Tp, _Up); #if __has_builtin(__builtin_is_corresponding_member) # ifndef __cpp_lib_is_layout_compatible # error "libstdc++ bug: is_corresponding_member and is_layout_compatible are provided but their FTM is not set" # endif /// @since C++20 template<typename _S1, typename _S2, typename _M1, typename _M2> constexpr bool is_corresponding_member(_M1 _S1::*__m1, _M2 _S2::*__m2) noexcept { return __builtin_is_corresponding_member(__m1, __m2); } #endif #endif #if __has_builtin(__is_pointer_interconvertible_base_of) \ && __cplusplus >= 202002L /// True if `_Derived` is standard-layout and has a base class of type `_Base` /// @since C++20 template<typename _Base, typename _Derived> struct is_pointer_interconvertible_base_of : bool_constant<__is_pointer_interconvertible_base_of(_Base, _Derived)> { }; /// @ingroup variable_templates /// @since C++20 template<typename _Base, typename _Derived> constexpr bool is_pointer_interconvertible_base_of_v = __is_pointer_interconvertible_base_of(_Base, _Derived); #if __has_builtin(__builtin_is_pointer_interconvertible_with_class) # ifndef __cpp_lib_is_pointer_interconvertible # error "libstdc++ bug: is_pointer_interconvertible available but FTM is not set" # endif /// True if `__mp` points to the first member of a standard-layout type /// @returns true if `s.*__mp` is pointer-interconvertible with `s` /// @since C++20 template<typename _Tp, typename _Mem> constexpr bool is_pointer_interconvertible_with_class(_Mem _Tp::*__mp) noexcept { return __builtin_is_pointer_interconvertible_with_class(__mp); } #endif #endif #ifdef __cpp_lib_is_scoped_enum // C++ >= 23 /// True if the type is a scoped enumeration type. /// @since C++23 # if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scoped_enum) template<typename _Tp> struct is_scoped_enum : bool_constant<__is_scoped_enum(_Tp)> { }; # else template<typename _Tp> struct is_scoped_enum : false_type { }; template<typename _Tp> requires __is_enum(_Tp) && requires(remove_cv_t<_Tp> __t) { __t = __t; } // fails if incomplete struct is_scoped_enum<_Tp> : bool_constant<!requires(_Tp __t, void(*__f)(int)) { __f(__t); }> { }; # endif /// @ingroup variable_templates /// @since C++23 # if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scoped_enum) template<typename _Tp> inline constexpr bool is_scoped_enum_v = __is_scoped_enum(_Tp); # else template<typename _Tp> inline constexpr bool is_scoped_enum_v = is_scoped_enum<_Tp>::value; # endif #endif #ifdef __cpp_lib_reference_from_temporary // C++ >= 23 && ref_{converts,constructs}_from_temp /// True if _Tp is a reference type, a _Up value can be bound to _Tp in /// direct-initialization, and a temporary object would be bound to /// the reference, false otherwise. /// @since C++23 template<typename _Tp, typename _Up> struct reference_constructs_from_temporary : public bool_constant<__reference_constructs_from_temporary(_Tp, _Up)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}) && std::__is_complete_or_unbounded(__type_identity<_Up>{}), "template argument must be a complete class or an unbounded array"); }; /// True if _Tp is a reference type, a _Up value can be bound to _Tp in /// copy-initialization, and a temporary object would be bound to /// the reference, false otherwise. /// @since C++23 template<typename _Tp, typename _Up> struct reference_converts_from_temporary : public bool_constant<__reference_converts_from_temporary(_Tp, _Up)> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}) && std::__is_complete_or_unbounded(__type_identity<_Up>{}), "template argument must be a complete class or an unbounded array"); }; /// @ingroup variable_templates /// @since C++23 template<typename _Tp, typename _Up> inline constexpr bool reference_constructs_from_temporary_v = reference_constructs_from_temporary<_Tp, _Up>::value; /// @ingroup variable_templates /// @since C++23 template<typename _Tp, typename _Up> inline constexpr bool reference_converts_from_temporary_v = reference_converts_from_temporary<_Tp, _Up>::value; #endif // __cpp_lib_reference_from_temporary #ifdef __cpp_lib_is_constant_evaluated // C++ >= 20 && HAVE_IS_CONST_EVAL /// Returns true only when called during constant evaluation. /// @since C++20 [[__gnu__::__always_inline__]] constexpr bool is_constant_evaluated() noexcept { #if __cpp_if_consteval >= 202106L if consteval { return true; } else { return false; } #else return __builtin_is_constant_evaluated(); #endif } #endif #if __cplusplus >= 202002L /// @cond undocumented template<typename _From, typename _To> using __copy_cv = typename __match_cv_qualifiers<_From, _To>::__type; template<typename _Xp, typename _Yp> using __cond_res = decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()()); template<typename _Ap, typename _Bp, typename = void> struct __common_ref_impl { }; // [meta.trans.other], COMMON-REF(A, B) template<typename _Ap, typename _Bp> using __common_ref = typename __common_ref_impl<_Ap, _Bp>::type; // COND-RES(COPYCV(X, Y) &, COPYCV(Y, X) &) template<typename _Xp, typename _Yp> using __condres_cvref = __cond_res<__copy_cv<_Xp, _Yp>&, __copy_cv<_Yp, _Xp>&>; // If A and B are both lvalue reference types, ... template<typename _Xp, typename _Yp> struct __common_ref_impl<_Xp&, _Yp&, __void_t<__condres_cvref<_Xp, _Yp>>> : enable_if<is_reference_v<__condres_cvref<_Xp, _Yp>>, __condres_cvref<_Xp, _Yp>> { }; // let C be remove_reference_t<COMMON-REF(X&, Y&)>&& template<typename _Xp, typename _Yp> using __common_ref_C = remove_reference_t<__common_ref<_Xp&, _Yp&>>&&; // If A and B are both rvalue reference types, ... template<typename _Xp, typename _Yp> struct __common_ref_impl<_Xp&&, _Yp&&, _Require<is_convertible<_Xp&&, __common_ref_C<_Xp, _Yp>>, is_convertible<_Yp&&, __common_ref_C<_Xp, _Yp>>>> { using type = __common_ref_C<_Xp, _Yp>; }; // let D be COMMON-REF(const X&, Y&) template<typename _Xp, typename _Yp> using __common_ref_D = __common_ref<const _Xp&, _Yp&>; // If A is an rvalue reference and B is an lvalue reference, ... template<typename _Xp, typename _Yp> struct __common_ref_impl<_Xp&&, _Yp&, _Require<is_convertible<_Xp&&, __common_ref_D<_Xp, _Yp>>>> { using type = __common_ref_D<_Xp, _Yp>; }; // If A is an lvalue reference and B is an rvalue reference, ... template<typename _Xp, typename _Yp> struct __common_ref_impl<_Xp&, _Yp&&> : __common_ref_impl<_Yp&&, _Xp&> { }; /// @endcond template<typename _Tp, typename _Up, template<typename> class _TQual, template<typename> class _UQual> struct basic_common_reference { }; /// @cond undocumented template<typename _Tp> struct __xref { template<typename _Up> using __type = __copy_cv<_Tp, _Up>; }; template<typename _Tp> struct __xref<_Tp&> { template<typename _Up> using __type = __copy_cv<_Tp, _Up>&; }; template<typename _Tp> struct __xref<_Tp&&> { template<typename _Up> using __type = __copy_cv<_Tp, _Up>&&; }; template<typename _Tp1, typename _Tp2> using __basic_common_ref = typename basic_common_reference<remove_cvref_t<_Tp1>, remove_cvref_t<_Tp2>, __xref<_Tp1>::template __type, __xref<_Tp2>::template __type>::type; /// @endcond template<typename... _Tp> struct common_reference; template<typename... _Tp> using common_reference_t = typename common_reference<_Tp...>::type; // If sizeof...(T) is zero, there shall be no member type. template<> struct common_reference<> { }; // If sizeof...(T) is one ... template<typename _Tp0> struct common_reference<_Tp0> { using type = _Tp0; }; /// @cond undocumented template<typename _Tp1, typename _Tp2, int _Bullet = 1, typename = void> struct __common_reference_impl : __common_reference_impl<_Tp1, _Tp2, _Bullet + 1> { }; // If sizeof...(T) is two ... template<typename _Tp1, typename _Tp2> struct common_reference<_Tp1, _Tp2> : __common_reference_impl<_Tp1, _Tp2> { }; // If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, ... template<typename _Tp1, typename _Tp2> struct __common_reference_impl<_Tp1&, _Tp2&, 1, void_t<__common_ref<_Tp1&, _Tp2&>>> { using type = __common_ref<_Tp1&, _Tp2&>; }; template<typename _Tp1, typename _Tp2> struct __common_reference_impl<_Tp1&&, _Tp2&&, 1, void_t<__common_ref<_Tp1&&, _Tp2&&>>> { using type = __common_ref<_Tp1&&, _Tp2&&>; }; template<typename _Tp1, typename _Tp2> struct __common_reference_impl<_Tp1&, _Tp2&&, 1, void_t<__common_ref<_Tp1&, _Tp2&&>>> { using type = __common_ref<_Tp1&, _Tp2&&>; }; template<typename _Tp1, typename _Tp2> struct __common_reference_impl<_Tp1&&, _Tp2&, 1, void_t<__common_ref<_Tp1&&, _Tp2&>>> { using type = __common_ref<_Tp1&&, _Tp2&>; }; // Otherwise, if basic_common_reference<...>::type is well-formed, ... template<typename _Tp1, typename _Tp2> struct __common_reference_impl<_Tp1, _Tp2, 2, void_t<__basic_common_ref<_Tp1, _Tp2>>> { using type = __basic_common_ref<_Tp1, _Tp2>; }; // Otherwise, if COND-RES(T1, T2) is well-formed, ... template<typename _Tp1, typename _Tp2> struct __common_reference_impl<_Tp1, _Tp2, 3, void_t<__cond_res<_Tp1, _Tp2>>> { using type = __cond_res<_Tp1, _Tp2>; }; // Otherwise, if common_type_t<T1, T2> is well-formed, ... template<typename _Tp1, typename _Tp2> struct __common_reference_impl<_Tp1, _Tp2, 4, void_t<common_type_t<_Tp1, _Tp2>>> { using type = common_type_t<_Tp1, _Tp2>; }; // Otherwise, there shall be no member type. template<typename _Tp1, typename _Tp2> struct __common_reference_impl<_Tp1, _Tp2, 5, void> { }; // Otherwise, if sizeof...(T) is greater than two, ... template<typename _Tp1, typename _Tp2, typename... _Rest> struct common_reference<_Tp1, _Tp2, _Rest...> : __common_type_fold<common_reference<_Tp1, _Tp2>, __common_type_pack<_Rest...>> { }; // Reuse __common_type_fold for common_reference<T1, T2, Rest...> template<typename _Tp1, typename _Tp2, typename... _Rest> struct __common_type_fold<common_reference<_Tp1, _Tp2>, __common_type_pack<_Rest...>, void_t<common_reference_t<_Tp1, _Tp2>>> : public common_reference<common_reference_t<_Tp1, _Tp2>, _Rest...> { }; /// @endcond #endif // C++2a #if __cplusplus >= 201103L // Stores a tuple of indices. Used by tuple and pair, and by bind() to // extract the elements in a tuple. template<size_t... _Indexes> struct _Index_tuple { }; // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. template<size_t _Num> struct _Build_index_tuple { #if __has_builtin(__make_integer_seq) template<typename, size_t... _Indices> using _IdxTuple = _Index_tuple<_Indices...>; // Clang defines __make_integer_seq for this purpose. using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; #else // For GCC and other compilers, use __integer_pack instead. using __type = _Index_tuple<__integer_pack(_Num)...>; #endif }; #endif // C++11 #if __cplusplus > 202302L template<typename _Tp> struct _CwFixedValue { using _S_type = _Tp; constexpr _CwFixedValue(_S_type __v) noexcept : _M_data(__v) { } _S_type _M_data; }; template<typename _Tp, size_t _Extent> struct _CwFixedValue<_Tp[_Extent]> { using _S_type = _Tp[_Extent]; constexpr _CwFixedValue(_Tp (&__arr)[_Extent]) noexcept : _CwFixedValue(__arr, typename _Build_index_tuple<_Extent>::__type()) { } template<size_t... _Indices> constexpr _CwFixedValue(_Tp (&__arr)[_Extent], _Index_tuple<_Indices...>) noexcept : _M_data{__arr[_Indices]...} { } _Tp _M_data[_Extent]; }; template<typename _Tp, size_t _Extent> _CwFixedValue(_Tp (&)[_Extent]) -> _CwFixedValue<_Tp[_Extent]>; template<_CwFixedValue _Tp, typename = typename decltype(_CwFixedValue(_Tp))::_S_type> struct constant_wrapper; template<typename _Tp> concept _ConstExprParam = requires { typename constant_wrapper<_Tp::value>; }; struct _CwOperators { template<_ConstExprParam _Tp> friend constexpr auto operator+(_Tp) noexcept -> constant_wrapper<(+_Tp::value)> { return {}; } template<_ConstExprParam _Tp> friend constexpr auto operator-(_Tp) noexcept -> constant_wrapper<(-_Tp::value)> { return {}; } template<_ConstExprParam _Tp> friend constexpr auto operator~(_Tp) noexcept -> constant_wrapper<(~_Tp::value)> { return {}; } template<_ConstExprParam _Tp> friend constexpr auto operator!(_Tp) noexcept -> constant_wrapper<(!_Tp::value)> { return {}; } template<_ConstExprParam _Tp> friend constexpr auto operator&(_Tp) noexcept -> constant_wrapper<(&_Tp::value)> { return {}; } template<_ConstExprParam _Tp> friend constexpr auto operator*(_Tp) noexcept -> constant_wrapper<(*_Tp::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator+(_Left, _Right) noexcept -> constant_wrapper<(_Left::value + _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator-(_Left, _Right) noexcept -> constant_wrapper<(_Left::value - _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator*(_Left, _Right) noexcept -> constant_wrapper<(_Left::value * _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator/(_Left, _Right) noexcept -> constant_wrapper<(_Left::value / _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator%(_Left, _Right) noexcept -> constant_wrapper<(_Left::value % _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator<<(_Left, _Right) noexcept -> constant_wrapper<(_Left::value << _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator>>(_Left, _Right) noexcept -> constant_wrapper<(_Left::value >> _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator&(_Left, _Right) noexcept -> constant_wrapper<(_Left::value & _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator|(_Left, _Right) noexcept -> constant_wrapper<(_Left::value | _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator^(_Left, _Right) noexcept -> constant_wrapper<(_Left::value ^ _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> requires (!is_constructible_v<bool, decltype(_Left::value)> || !is_constructible_v<bool, decltype(_Right::value)>) friend constexpr auto operator&&(_Left, _Right) noexcept -> constant_wrapper<(_Left::value && _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> requires (!is_constructible_v<bool, decltype(_Left::value)> || !is_constructible_v<bool, decltype(_Right::value)>) friend constexpr auto operator||(_Left, _Right) noexcept -> constant_wrapper<(_Left::value || _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator<=>(_Left, _Right) noexcept -> constant_wrapper<(_Left::value <=> _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator<(_Left, _Right) noexcept -> constant_wrapper<(_Left::value < _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator<=(_Left, _Right) noexcept -> constant_wrapper<(_Left::value <= _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator==(_Left, _Right) noexcept -> constant_wrapper<(_Left::value == _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator!=(_Left, _Right) noexcept -> constant_wrapper<(_Left::value != _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator>(_Left, _Right) noexcept -> constant_wrapper<(_Left::value > _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator>=(_Left, _Right) noexcept -> constant_wrapper<(_Left::value >= _Right::value)> { return {}; } template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator,(_Left, _Right) noexcept = delete; template<_ConstExprParam _Left, _ConstExprParam _Right> friend constexpr auto operator->*(_Left, _Right) noexcept -> constant_wrapper<_Left::value->*(_Right::value)> { return {}; } template<_ConstExprParam _Tp, _ConstExprParam... _Args> constexpr auto operator()(this _Tp, _Args...) noexcept requires requires(_Args...) { constant_wrapper<_Tp::value(_Args::value...)>(); } { return constant_wrapper<_Tp::value(_Args::value...)>{}; } template<_ConstExprParam _Tp, _ConstExprParam... _Args> constexpr auto operator[](this _Tp, _Args...) noexcept -> constant_wrapper<(_Tp::value[_Args::value...])> { return {}; } template<_ConstExprParam _Tp> constexpr auto operator++(this _Tp) noexcept requires requires(_Tp::value_type __x) { ++__x; } { return constant_wrapper< [] { auto __x = _Tp::value; return ++__x; }()>{}; } template<_ConstExprParam _Tp> constexpr auto operator++(this _Tp, int) noexcept requires requires(_Tp::value_type __x) { __x++; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x++; }()>{}; } template<_ConstExprParam _Tp> constexpr auto operator--(this _Tp) noexcept requires requires(_Tp::value_type __x) { --__x; } { return constant_wrapper< [] { auto __x = _Tp::value; return --__x; }()>{}; } template<_ConstExprParam _Tp> constexpr auto operator--(this _Tp, int) noexcept requires requires(_Tp::value_type __x) { __x--; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x--; }()>{}; } template<_ConstExprParam _Tp, _ConstExprParam _Right> constexpr auto operator+=(this _Tp, _Right) noexcept requires requires(_Tp::value_type __x) { __x += _Right::value; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x += _Right::value; }()>{}; } template<_ConstExprParam _Tp, _ConstExprParam _Right> constexpr auto operator-=(this _Tp, _Right) noexcept requires requires(_Tp::value_type __x) { __x -= _Right::value; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x -= _Right::value; }()>{}; } template<_ConstExprParam _Tp, _ConstExprParam _Right> constexpr auto operator*=(this _Tp, _Right) noexcept requires requires(_Tp::value_type __x) { __x *= _Right::value; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x *= _Right::value; }()>{}; } template<_ConstExprParam _Tp, _ConstExprParam _Right> constexpr auto operator/=(this _Tp, _Right) noexcept requires requires(_Tp::value_type __x) { __x /= _Right::value; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x /= _Right::value; }()>{}; } template<_ConstExprParam _Tp, _ConstExprParam _Right> constexpr auto operator%=(this _Tp, _Right) noexcept requires requires(_Tp::value_type __x) { __x %= _Right::value; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x %= _Right::value; }()>{}; } template<_ConstExprParam _Tp, _ConstExprParam _Right> constexpr auto operator&=(this _Tp, _Right) noexcept requires requires(_Tp::value_type __x) { __x &= _Right::value; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x &= _Right::value; }()>{}; } template<_ConstExprParam _Tp, _ConstExprParam _Right> constexpr auto operator|=(this _Tp, _Right) noexcept requires requires(_Tp::value_type __x) { __x |= _Right::value; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x |= _Right::value; }()>{}; } template<_ConstExprParam _Tp, _ConstExprParam _Right> constexpr auto operator^=(this _Tp, _Right) noexcept requires requires(_Tp::value_type __x) { __x ^= _Right::value; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x ^= _Right::value; }()>{}; } template<_ConstExprParam _Tp, _ConstExprParam _Right> constexpr auto operator<<=(this _Tp, _Right) noexcept requires requires(_Tp::value_type __x) { __x <<= _Right::value; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x <<= _Right::value; }()>{}; } template<_ConstExprParam _Tp, _ConstExprParam _Right> constexpr auto operator>>=(this _Tp, _Right) noexcept requires requires(_Tp::value_type __x) { __x >>= _Right::value; } { return constant_wrapper< [] { auto __x = _Tp::value; return __x >>= _Right::value; }()>{}; } }; template<_CwFixedValue _Xv, typename> struct constant_wrapper : _CwOperators { static constexpr const auto& value = _Xv._M_data; using type = constant_wrapper; using value_type = typename decltype(_Xv)::_S_type; template<_ConstExprParam _Right> constexpr auto operator=(_Right) const noexcept requires requires(value_type __x) { __x = _Right::value; } { return constant_wrapper< [] { auto __x = value; return __x = _Right::value; }()>{}; } constexpr operator decltype(auto)() const noexcept { return value; } }; template<_CwFixedValue _Tp> constexpr auto cw = constant_wrapper<_Tp>{}; #endif /// @} group metaprogramming _GLIBCXX_END_NAMESPACE_VERSION } // namespace std } // extern "C++" #endif // C++11 #endif // _GLIBCXX_TYPE_TRAITS template<class> struct ExtractCW {}; template<auto V, class T> struct ExtractCW<std::constant_wrapper<V, T>> { using type = decltype(V); }; template<auto V> using ExtractedCWFixedValue = ExtractCW<std::remove_cvref_t<decltype(std::cw<V>)>>::type; int main() { ExtractedCWFixedValue<1> x [[maybe_unused]] = 1; }
Become a Patron
Sponsor on GitHub
Donate via PayPal
Compiler Explorer Shop
Source on GitHub
Mailing list
Installed libraries
Wiki
Report an issue
How it works
Contact the author
CE on Mastodon
CE on Bluesky
Statistics
Changelog
Version tree