Thanks for using Compiler Explorer
Sponsors
Jakt
C++
Ada
Analysis
Android Java
Android Kotlin
Assembly
C
C3
Carbon
C++ (Circle)
CIRCT
Clean
CMake
CMakeScript
COBOL
C++ for OpenCL
MLIR
Cppx
Cppx-Blue
Cppx-Gold
Cpp2-cppfront
Crystal
C#
CUDA C++
D
Dart
Elixir
Erlang
Fortran
F#
GLSL
Go
Haskell
HLSL
Hook
Hylo
IL
ispc
Java
Julia
Kotlin
LLVM IR
LLVM MIR
Modula-2
Nim
Objective-C
Objective-C++
OCaml
OpenCL C
Pascal
Pony
Python
Racket
Ruby
Rust
Snowball
Scala
Solidity
Spice
Swift
LLVM TableGen
Toit
TypeScript Native
V
Vala
Visual Basic
WASM
Zig
Javascript
GIMPLE
c++ source #1
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
6502-c++ 11.1.0
ARM GCC 10.2.0
ARM GCC 10.3.0
ARM GCC 10.4.0
ARM GCC 10.5.0
ARM GCC 11.1.0
ARM GCC 11.2.0
ARM GCC 11.3.0
ARM GCC 11.4.0
ARM GCC 12.1.0
ARM GCC 12.2.0
ARM GCC 12.3.0
ARM GCC 12.4.0
ARM GCC 13.1.0
ARM GCC 13.2.0
ARM GCC 13.2.0 (unknown-eabi)
ARM GCC 13.3.0
ARM GCC 13.3.0 (unknown-eabi)
ARM GCC 14.1.0
ARM GCC 14.1.0 (unknown-eabi)
ARM GCC 14.2.0
ARM GCC 14.2.0 (unknown-eabi)
ARM GCC 4.5.4
ARM GCC 4.6.4
ARM GCC 5.4
ARM GCC 6.3.0
ARM GCC 6.4.0
ARM GCC 7.3.0
ARM GCC 7.5.0
ARM GCC 8.2.0
ARM GCC 8.5.0
ARM GCC 9.3.0
ARM GCC 9.4.0
ARM GCC 9.5.0
ARM GCC trunk
ARM gcc 10.2.1 (none)
ARM gcc 10.3.1 (2021.07 none)
ARM gcc 10.3.1 (2021.10 none)
ARM gcc 11.2.1 (none)
ARM gcc 5.4.1 (none)
ARM gcc 7.2.1 (none)
ARM gcc 8.2 (WinCE)
ARM gcc 8.3.1 (none)
ARM gcc 9.2.1 (none)
ARM msvc v19.0 (WINE)
ARM msvc v19.10 (WINE)
ARM msvc v19.14 (WINE)
ARM64 Morello gcc 10.1 Alpha 2
ARM64 gcc 10.2
ARM64 gcc 10.3
ARM64 gcc 10.4
ARM64 gcc 10.5.0
ARM64 gcc 11.1
ARM64 gcc 11.2
ARM64 gcc 11.3
ARM64 gcc 11.4.0
ARM64 gcc 12.1
ARM64 gcc 12.2.0
ARM64 gcc 12.3.0
ARM64 gcc 12.4.0
ARM64 gcc 13.1.0
ARM64 gcc 13.2.0
ARM64 gcc 13.3.0
ARM64 gcc 14.1.0
ARM64 gcc 14.2.0
ARM64 gcc 4.9.4
ARM64 gcc 5.4
ARM64 gcc 5.5.0
ARM64 gcc 6.3
ARM64 gcc 6.4
ARM64 gcc 7.3
ARM64 gcc 7.5
ARM64 gcc 8.2
ARM64 gcc 8.5
ARM64 gcc 9.3
ARM64 gcc 9.4
ARM64 gcc 9.5
ARM64 gcc trunk
ARM64 msvc v19.14 (WINE)
AVR gcc 10.3.0
AVR gcc 11.1.0
AVR gcc 12.1.0
AVR gcc 12.2.0
AVR gcc 12.3.0
AVR gcc 12.4.0
AVR gcc 13.1.0
AVR gcc 13.2.0
AVR gcc 13.3.0
AVR gcc 14.1.0
AVR gcc 14.2.0
AVR gcc 4.5.4
AVR gcc 4.6.4
AVR gcc 5.4.0
AVR gcc 9.2.0
AVR gcc 9.3.0
Arduino Mega (1.8.9)
Arduino Uno (1.8.9)
BPF clang (trunk)
BPF clang 13.0.0
BPF clang 14.0.0
BPF clang 15.0.0
BPF clang 16.0.0
BPF clang 17.0.1
BPF clang 18.1.0
BPF clang 19.1.0
BPF gcc 13.1.0
BPF gcc 13.2.0
BPF gcc 13.3.0
BPF gcc trunk
EDG (experimental reflection)
EDG 6.5
EDG 6.5 (GNU mode gcc 13)
EDG 6.6
EDG 6.6 (GNU mode gcc 13)
FRC 2019
FRC 2020
FRC 2023
HPPA gcc 14.2.0
KVX ACB 4.1.0 (GCC 7.5.0)
KVX ACB 4.1.0-cd1 (GCC 7.5.0)
KVX ACB 4.10.0 (GCC 10.3.1)
KVX ACB 4.11.1 (GCC 10.3.1)
KVX ACB 4.12.0 (GCC 11.3.0)
KVX ACB 4.2.0 (GCC 7.5.0)
KVX ACB 4.3.0 (GCC 7.5.0)
KVX ACB 4.4.0 (GCC 7.5.0)
KVX ACB 4.6.0 (GCC 9.4.1)
KVX ACB 4.8.0 (GCC 9.4.1)
KVX ACB 4.9.0 (GCC 9.4.1)
KVX ACB 5.0.0 (GCC 12.2.1)
LoongArch64 clang (trunk)
LoongArch64 clang 17.0.1
LoongArch64 clang 18.1.0
LoongArch64 clang 19.1.0
M68K gcc 13.1.0
M68K gcc 13.2.0
M68K gcc 13.3.0
M68K gcc 14.1.0
M68K gcc 14.2.0
M68k clang (trunk)
MRISC32 gcc (trunk)
MSP430 gcc 4.5.3
MSP430 gcc 5.3.0
MSP430 gcc 6.2.1
MinGW clang 14.0.3
MinGW clang 14.0.6
MinGW clang 15.0.7
MinGW clang 16.0.0
MinGW clang 16.0.2
MinGW gcc 11.3.0
MinGW gcc 12.1.0
MinGW gcc 12.2.0
MinGW gcc 13.1.0
RISC-V (32-bits) gcc (trunk)
RISC-V (32-bits) gcc 10.2.0
RISC-V (32-bits) gcc 10.3.0
RISC-V (32-bits) gcc 11.2.0
RISC-V (32-bits) gcc 11.3.0
RISC-V (32-bits) gcc 11.4.0
RISC-V (32-bits) gcc 12.1.0
RISC-V (32-bits) gcc 12.2.0
RISC-V (32-bits) gcc 12.3.0
RISC-V (32-bits) gcc 12.4.0
RISC-V (32-bits) gcc 13.1.0
RISC-V (32-bits) gcc 13.2.0
RISC-V (32-bits) gcc 13.3.0
RISC-V (32-bits) gcc 14.1.0
RISC-V (32-bits) gcc 14.2.0
RISC-V (32-bits) gcc 8.2.0
RISC-V (32-bits) gcc 8.5.0
RISC-V (32-bits) gcc 9.4.0
RISC-V (64-bits) gcc (trunk)
RISC-V (64-bits) gcc 10.2.0
RISC-V (64-bits) gcc 10.3.0
RISC-V (64-bits) gcc 11.2.0
RISC-V (64-bits) gcc 11.3.0
RISC-V (64-bits) gcc 11.4.0
RISC-V (64-bits) gcc 12.1.0
RISC-V (64-bits) gcc 12.2.0
RISC-V (64-bits) gcc 12.3.0
RISC-V (64-bits) gcc 12.4.0
RISC-V (64-bits) gcc 13.1.0
RISC-V (64-bits) gcc 13.2.0
RISC-V (64-bits) gcc 13.3.0
RISC-V (64-bits) gcc 14.1.0
RISC-V (64-bits) gcc 14.2.0
RISC-V (64-bits) gcc 8.2.0
RISC-V (64-bits) gcc 8.5.0
RISC-V (64-bits) gcc 9.4.0
RISC-V rv32gc clang (trunk)
RISC-V rv32gc clang 10.0.0
RISC-V rv32gc clang 10.0.1
RISC-V rv32gc clang 11.0.0
RISC-V rv32gc clang 11.0.1
RISC-V rv32gc clang 12.0.0
RISC-V rv32gc clang 12.0.1
RISC-V rv32gc clang 13.0.0
RISC-V rv32gc clang 13.0.1
RISC-V rv32gc clang 14.0.0
RISC-V rv32gc clang 15.0.0
RISC-V rv32gc clang 16.0.0
RISC-V rv32gc clang 17.0.1
RISC-V rv32gc clang 18.1.0
RISC-V rv32gc clang 19.1.0
RISC-V rv32gc clang 9.0.0
RISC-V rv32gc clang 9.0.1
RISC-V rv64gc clang (trunk)
RISC-V rv64gc clang 10.0.0
RISC-V rv64gc clang 10.0.1
RISC-V rv64gc clang 11.0.0
RISC-V rv64gc clang 11.0.1
RISC-V rv64gc clang 12.0.0
RISC-V rv64gc clang 12.0.1
RISC-V rv64gc clang 13.0.0
RISC-V rv64gc clang 13.0.1
RISC-V rv64gc clang 14.0.0
RISC-V rv64gc clang 15.0.0
RISC-V rv64gc clang 16.0.0
RISC-V rv64gc clang 17.0.1
RISC-V rv64gc clang 18.1.0
RISC-V rv64gc clang 19.1.0
RISC-V rv64gc clang 9.0.0
RISC-V rv64gc clang 9.0.1
Raspbian Buster
Raspbian Stretch
SPARC LEON gcc 12.2.0
SPARC LEON gcc 12.3.0
SPARC LEON gcc 12.4.0
SPARC LEON gcc 13.1.0
SPARC LEON gcc 13.2.0
SPARC LEON gcc 13.3.0
SPARC LEON gcc 14.1.0
SPARC LEON gcc 14.2.0
SPARC gcc 12.2.0
SPARC gcc 12.3.0
SPARC gcc 12.4.0
SPARC gcc 13.1.0
SPARC gcc 13.2.0
SPARC gcc 13.3.0
SPARC gcc 14.1.0
SPARC gcc 14.2.0
SPARC64 gcc 12.2.0
SPARC64 gcc 12.3.0
SPARC64 gcc 12.4.0
SPARC64 gcc 13.1.0
SPARC64 gcc 13.2.0
SPARC64 gcc 13.3.0
SPARC64 gcc 14.1.0
SPARC64 gcc 14.2.0
TI C6x gcc 12.2.0
TI C6x gcc 12.3.0
TI C6x gcc 12.4.0
TI C6x gcc 13.1.0
TI C6x gcc 13.2.0
TI C6x gcc 13.3.0
TI C6x gcc 14.1.0
TI C6x gcc 14.2.0
TI CL430 21.6.1
VAX gcc NetBSDELF 10.4.0
VAX gcc NetBSDELF 10.5.0 (Nov 15 03:50:22 2023)
WebAssembly clang (trunk)
Xtensa ESP32 gcc 11.2.0 (2022r1)
Xtensa ESP32 gcc 12.2.0 (20230208)
Xtensa ESP32 gcc 8.2.0 (2019r2)
Xtensa ESP32 gcc 8.2.0 (2020r1)
Xtensa ESP32 gcc 8.2.0 (2020r2)
Xtensa ESP32 gcc 8.4.0 (2020r3)
Xtensa ESP32 gcc 8.4.0 (2021r1)
Xtensa ESP32 gcc 8.4.0 (2021r2)
Xtensa ESP32-S2 gcc 11.2.0 (2022r1)
Xtensa ESP32-S2 gcc 12.2.0 (20230208)
Xtensa ESP32-S2 gcc 8.2.0 (2019r2)
Xtensa ESP32-S2 gcc 8.2.0 (2020r1)
Xtensa ESP32-S2 gcc 8.2.0 (2020r2)
Xtensa ESP32-S2 gcc 8.4.0 (2020r3)
Xtensa ESP32-S2 gcc 8.4.0 (2021r1)
Xtensa ESP32-S2 gcc 8.4.0 (2021r2)
Xtensa ESP32-S3 gcc 11.2.0 (2022r1)
Xtensa ESP32-S3 gcc 12.2.0 (20230208)
Xtensa ESP32-S3 gcc 8.4.0 (2020r3)
Xtensa ESP32-S3 gcc 8.4.0 (2021r1)
Xtensa ESP32-S3 gcc 8.4.0 (2021r2)
arm64 msvc v19.20 VS16.0
arm64 msvc v19.21 VS16.1
arm64 msvc v19.22 VS16.2
arm64 msvc v19.23 VS16.3
arm64 msvc v19.24 VS16.4
arm64 msvc v19.25 VS16.5
arm64 msvc v19.27 VS16.7
arm64 msvc v19.28 VS16.8
arm64 msvc v19.28 VS16.9
arm64 msvc v19.29 VS16.10
arm64 msvc v19.29 VS16.11
arm64 msvc v19.30 VS17.0
arm64 msvc v19.31 VS17.1
arm64 msvc v19.32 VS17.2
arm64 msvc v19.33 VS17.3
arm64 msvc v19.34 VS17.4
arm64 msvc v19.35 VS17.5
arm64 msvc v19.36 VS17.6
arm64 msvc v19.37 VS17.7
arm64 msvc v19.38 VS17.8
arm64 msvc v19.39 VS17.9
arm64 msvc v19.40 VS17.10
arm64 msvc v19.latest
armv7-a clang (trunk)
armv7-a clang 10.0.0
armv7-a clang 10.0.1
armv7-a clang 11.0.0
armv7-a clang 11.0.1
armv7-a clang 12.0.0
armv7-a clang 12.0.1
armv7-a clang 13.0.0
armv7-a clang 13.0.1
armv7-a clang 14.0.0
armv7-a clang 15.0.0
armv7-a clang 16.0.0
armv7-a clang 17.0.1
armv7-a clang 18.1.0
armv7-a clang 19.1.0
armv7-a clang 9.0.0
armv7-a clang 9.0.1
armv8-a clang (all architectural features, trunk)
armv8-a clang (trunk)
armv8-a clang 10.0.0
armv8-a clang 10.0.1
armv8-a clang 11.0.0
armv8-a clang 11.0.1
armv8-a clang 12.0.0
armv8-a clang 13.0.0
armv8-a clang 14.0.0
armv8-a clang 15.0.0
armv8-a clang 16.0.0
armv8-a clang 17.0.1
armv8-a clang 18.1.0
armv8-a clang 19.1.0
armv8-a clang 9.0.0
armv8-a clang 9.0.1
clang-cl 18.1.0
ellcc 0.1.33
ellcc 0.1.34
ellcc 2017-07-16
hexagon-clang 16.0.5
llvm-mos atari2600-3e
llvm-mos atari2600-4k
llvm-mos atari2600-common
llvm-mos atari5200-supercart
llvm-mos atari8-cart-megacart
llvm-mos atari8-cart-std
llvm-mos atari8-cart-xegs
llvm-mos atari8-common
llvm-mos atari8-dos
llvm-mos c128
llvm-mos c64
llvm-mos commodore
llvm-mos cpm65
llvm-mos cx16
llvm-mos dodo
llvm-mos eater
llvm-mos mega65
llvm-mos nes
llvm-mos nes-action53
llvm-mos nes-cnrom
llvm-mos nes-gtrom
llvm-mos nes-mmc1
llvm-mos nes-mmc3
llvm-mos nes-nrom
llvm-mos nes-unrom
llvm-mos nes-unrom-512
llvm-mos osi-c1p
llvm-mos pce
llvm-mos pce-cd
llvm-mos pce-common
llvm-mos pet
llvm-mos rp6502
llvm-mos rpc8e
llvm-mos supervision
llvm-mos vic20
loongarch64 gcc 12.2.0
loongarch64 gcc 12.3.0
loongarch64 gcc 12.4.0
loongarch64 gcc 13.1.0
loongarch64 gcc 13.2.0
loongarch64 gcc 13.3.0
loongarch64 gcc 14.1.0
loongarch64 gcc 14.2.0
mips clang 13.0.0
mips clang 14.0.0
mips clang 15.0.0
mips clang 16.0.0
mips clang 17.0.1
mips clang 18.1.0
mips clang 19.1.0
mips gcc 11.2.0
mips gcc 12.1.0
mips gcc 12.2.0
mips gcc 12.3.0
mips gcc 12.4.0
mips gcc 13.1.0
mips gcc 13.2.0
mips gcc 13.3.0
mips gcc 14.1.0
mips gcc 14.2.0
mips gcc 4.9.4
mips gcc 5.4
mips gcc 5.5.0
mips gcc 9.3.0 (codescape)
mips gcc 9.5.0
mips64 (el) gcc 12.1.0
mips64 (el) gcc 12.2.0
mips64 (el) gcc 12.3.0
mips64 (el) gcc 12.4.0
mips64 (el) gcc 13.1.0
mips64 (el) gcc 13.2.0
mips64 (el) gcc 13.3.0
mips64 (el) gcc 14.1.0
mips64 (el) gcc 14.2.0
mips64 (el) gcc 4.9.4
mips64 (el) gcc 5.4.0
mips64 (el) gcc 5.5.0
mips64 (el) gcc 9.5.0
mips64 clang 13.0.0
mips64 clang 14.0.0
mips64 clang 15.0.0
mips64 clang 16.0.0
mips64 clang 17.0.1
mips64 clang 18.1.0
mips64 clang 19.1.0
mips64 gcc 11.2.0
mips64 gcc 12.1.0
mips64 gcc 12.2.0
mips64 gcc 12.3.0
mips64 gcc 12.4.0
mips64 gcc 13.1.0
mips64 gcc 13.2.0
mips64 gcc 13.3.0
mips64 gcc 14.1.0
mips64 gcc 14.2.0
mips64 gcc 4.9.4
mips64 gcc 5.4.0
mips64 gcc 5.5.0
mips64 gcc 9.5.0
mips64el clang 13.0.0
mips64el clang 14.0.0
mips64el clang 15.0.0
mips64el clang 16.0.0
mips64el clang 17.0.1
mips64el clang 18.1.0
mips64el clang 19.1.0
mipsel clang 13.0.0
mipsel clang 14.0.0
mipsel clang 15.0.0
mipsel clang 16.0.0
mipsel clang 17.0.1
mipsel clang 18.1.0
mipsel clang 19.1.0
mipsel gcc 12.1.0
mipsel gcc 12.2.0
mipsel gcc 12.3.0
mipsel gcc 12.4.0
mipsel gcc 13.1.0
mipsel gcc 13.2.0
mipsel gcc 13.3.0
mipsel gcc 14.1.0
mipsel gcc 14.2.0
mipsel gcc 4.9.4
mipsel gcc 5.4.0
mipsel gcc 5.5.0
mipsel gcc 9.5.0
nanoMIPS gcc 6.3.0 (mtk)
power gcc 11.2.0
power gcc 12.1.0
power gcc 12.2.0
power gcc 12.3.0
power gcc 12.4.0
power gcc 13.1.0
power gcc 13.2.0
power gcc 13.3.0
power gcc 14.1.0
power gcc 14.2.0
power gcc 4.8.5
power64 AT12.0 (gcc8)
power64 AT13.0 (gcc9)
power64 gcc 11.2.0
power64 gcc 12.1.0
power64 gcc 12.2.0
power64 gcc 12.3.0
power64 gcc 12.4.0
power64 gcc 13.1.0
power64 gcc 13.2.0
power64 gcc 13.3.0
power64 gcc 14.1.0
power64 gcc 14.2.0
power64 gcc trunk
power64le AT12.0 (gcc8)
power64le AT13.0 (gcc9)
power64le clang (trunk)
power64le gcc 11.2.0
power64le gcc 12.1.0
power64le gcc 12.2.0
power64le gcc 12.3.0
power64le gcc 12.4.0
power64le gcc 13.1.0
power64le gcc 13.2.0
power64le gcc 13.3.0
power64le gcc 14.1.0
power64le gcc 14.2.0
power64le gcc 6.3.0
power64le gcc trunk
powerpc64 clang (trunk)
s390x gcc 11.2.0
s390x gcc 12.1.0
s390x gcc 12.2.0
s390x gcc 12.3.0
s390x gcc 12.4.0
s390x gcc 13.1.0
s390x gcc 13.2.0
s390x gcc 13.3.0
s390x gcc 14.1.0
s390x gcc 14.2.0
sh gcc 12.2.0
sh gcc 12.3.0
sh gcc 12.4.0
sh gcc 13.1.0
sh gcc 13.2.0
sh gcc 13.3.0
sh gcc 14.1.0
sh gcc 14.2.0
sh gcc 4.9.4
sh gcc 9.5.0
vast (trunk)
x64 msvc v19.0 (WINE)
x64 msvc v19.10 (WINE)
x64 msvc v19.14 (WINE)
x64 msvc v19.20 VS16.0
x64 msvc v19.21 VS16.1
x64 msvc v19.22 VS16.2
x64 msvc v19.23 VS16.3
x64 msvc v19.24 VS16.4
x64 msvc v19.25 VS16.5
x64 msvc v19.27 VS16.7
x64 msvc v19.28 VS16.8
x64 msvc v19.28 VS16.9
x64 msvc v19.29 VS16.10
x64 msvc v19.29 VS16.11
x64 msvc v19.30 VS17.0
x64 msvc v19.31 VS17.1
x64 msvc v19.32 VS17.2
x64 msvc v19.33 VS17.3
x64 msvc v19.34 VS17.4
x64 msvc v19.35 VS17.5
x64 msvc v19.36 VS17.6
x64 msvc v19.37 VS17.7
x64 msvc v19.38 VS17.8
x64 msvc v19.39 VS17.9
x64 msvc v19.40 VS17.10
x64 msvc v19.latest
x86 djgpp 4.9.4
x86 djgpp 5.5.0
x86 djgpp 6.4.0
x86 djgpp 7.2.0
x86 msvc v19.0 (WINE)
x86 msvc v19.10 (WINE)
x86 msvc v19.14 (WINE)
x86 msvc v19.20 VS16.0
x86 msvc v19.21 VS16.1
x86 msvc v19.22 VS16.2
x86 msvc v19.23 VS16.3
x86 msvc v19.24 VS16.4
x86 msvc v19.25 VS16.5
x86 msvc v19.27 VS16.7
x86 msvc v19.28 VS16.8
x86 msvc v19.28 VS16.9
x86 msvc v19.29 VS16.10
x86 msvc v19.29 VS16.11
x86 msvc v19.30 VS17.0
x86 msvc v19.31 VS17.1
x86 msvc v19.32 VS17.2
x86 msvc v19.33 VS17.3
x86 msvc v19.34 VS17.4
x86 msvc v19.35 VS17.5
x86 msvc v19.36 VS17.6
x86 msvc v19.37 VS17.7
x86 msvc v19.38 VS17.8
x86 msvc v19.39 VS17.9
x86 msvc v19.40 VS17.10
x86 msvc v19.latest
x86 nvc++ 22.11
x86 nvc++ 22.7
x86 nvc++ 22.9
x86 nvc++ 23.1
x86 nvc++ 23.11
x86 nvc++ 23.3
x86 nvc++ 23.5
x86 nvc++ 23.7
x86 nvc++ 23.9
x86 nvc++ 24.1
x86 nvc++ 24.3
x86 nvc++ 24.5
x86 nvc++ 24.7
x86-64 Zapcc 190308
x86-64 clang (EricWF contracts)
x86-64 clang (amd-staging)
x86-64 clang (assertions trunk)
x86-64 clang (clangir)
x86-64 clang (dascandy contracts)
x86-64 clang (experimental -Wlifetime)
x86-64 clang (experimental P1061)
x86-64 clang (experimental P1144)
x86-64 clang (experimental P1221)
x86-64 clang (experimental P2996)
x86-64 clang (experimental P3068)
x86-64 clang (experimental P3309)
x86-64 clang (experimental P3367)
x86-64 clang (experimental P3372)
x86-64 clang (experimental metaprogramming - P2632)
x86-64 clang (old concepts branch)
x86-64 clang (p1974)
x86-64 clang (pattern matching - P2688)
x86-64 clang (reflection)
x86-64 clang (resugar)
x86-64 clang (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 3.0.0
x86-64 clang 3.0.0 (assertions)
x86-64 clang 3.1
x86-64 clang 3.1 (assertions)
x86-64 clang 3.2
x86-64 clang 3.2 (assertions)
x86-64 clang 3.3
x86-64 clang 3.3 (assertions)
x86-64 clang 3.4 (assertions)
x86-64 clang 3.4.1
x86-64 clang 3.5
x86-64 clang 3.5 (assertions)
x86-64 clang 3.5.1
x86-64 clang 3.5.2
x86-64 clang 3.6
x86-64 clang 3.6 (assertions)
x86-64 clang 3.7
x86-64 clang 3.7 (assertions)
x86-64 clang 3.7.1
x86-64 clang 3.8
x86-64 clang 3.8 (assertions)
x86-64 clang 3.8.1
x86-64 clang 3.9.0
x86-64 clang 3.9.0 (assertions)
x86-64 clang 3.9.1
x86-64 clang 4.0.0
x86-64 clang 4.0.0 (assertions)
x86-64 clang 4.0.1
x86-64 clang 5.0.0
x86-64 clang 5.0.0 (assertions)
x86-64 clang 5.0.1
x86-64 clang 5.0.2
x86-64 clang 6.0.0
x86-64 clang 6.0.0 (assertions)
x86-64 clang 6.0.1
x86-64 clang 7.0.0
x86-64 clang 7.0.0 (assertions)
x86-64 clang 7.0.1
x86-64 clang 7.1.0
x86-64 clang 8.0.0
x86-64 clang 8.0.0 (assertions)
x86-64 clang 8.0.1
x86-64 clang 9.0.0
x86-64 clang 9.0.0 (assertions)
x86-64 clang 9.0.1
x86-64 clang rocm-4.5.2
x86-64 clang rocm-5.0.2
x86-64 clang rocm-5.1.3
x86-64 clang rocm-5.2.3
x86-64 clang rocm-5.3.3
x86-64 clang rocm-5.7.0
x86-64 clang rocm-6.0.2
x86-64 clang rocm-6.1.2
x86-64 gcc (contract labels)
x86-64 gcc (contracts natural syntax)
x86-64 gcc (contracts)
x86-64 gcc (coroutines)
x86-64 gcc (modules)
x86-64 gcc (trunk)
x86-64 gcc 10.1
x86-64 gcc 10.2
x86-64 gcc 10.3
x86-64 gcc 10.4
x86-64 gcc 10.5
x86-64 gcc 11.1
x86-64 gcc 11.2
x86-64 gcc 11.3
x86-64 gcc 11.4
x86-64 gcc 12.1
x86-64 gcc 12.2
x86-64 gcc 12.3
x86-64 gcc 12.4
x86-64 gcc 13.1
x86-64 gcc 13.2
x86-64 gcc 13.3
x86-64 gcc 14.1
x86-64 gcc 14.2
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 (latest)
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
zig c++ 0.10.0
zig c++ 0.11.0
zig c++ 0.12.0
zig c++ 0.12.1
zig c++ 0.13.0
zig c++ 0.6.0
zig c++ 0.7.0
zig c++ 0.7.1
zig c++ 0.8.0
zig c++ 0.9.0
zig c++ trunk
Options
Source code
// // Copyright (c) 2012-2019 Kris Jusiak (kris at jusiak dot net) // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // //#pragma once #if (__cplusplus < 201305L && _MSC_VER < 1900) #error "[Boost].DI requires C++14 support (Clang-3.4+, GCC-5.1+, MSVC-2015+)" #else #define BOOST_DI_VERSION 1'1'0 #define BOOST_DI_NAMESPACE_BEGIN \ namespace boost { \ namespace di { \ inline namespace v1_1_0 { #define BOOST_DI_NAMESPACE_END \ } \ } \ } #if !defined(BOOST_DI_CFG_DIAGNOSTICS_LEVEL) #define BOOST_DI_CFG_DIAGNOSTICS_LEVEL 1 #endif #if defined(BOOST_DI_CFG_FWD) BOOST_DI_CFG_FWD #endif #define __BOOST_DI_COMPILER(arg, ...) __BOOST_DI_COMPILER_IMPL(arg, __VA_ARGS__) #define __BOOST_DI_COMPILER_IMPL(arg, ...) arg##__VA_ARGS__ #if defined(__clang__) #define __CLANG__ __BOOST_DI_COMPILER(__clang_major__, __clang_minor__) #define __BOOST_DI_UNUSED __attribute__((unused)) #define __BOOST_DI_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] #define __BOOST_DI_TYPE_WKND(T) #define __BOOST_DI_ACCESS_WKND private #define __BOOST_DI_VARIABLE_TEMPLATE_INIT_WKND \ {} #elif defined(__GNUC__) #define __GCC__ #define __BOOST_DI_UNUSED __attribute__((unused)) #define __BOOST_DI_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] #define __BOOST_DI_TYPE_WKND(T) #define __BOOST_DI_ACCESS_WKND private #define __BOOST_DI_VARIABLE_TEMPLATE_INIT_WKND \ {} #elif defined(_MSC_VER) #define __MSVC__ #if !defined(__has_include) #define __has_include(...) 0 #endif #define __BOOST_DI_UNUSED #define __BOOST_DI_DEPRECATED(...) __declspec(deprecated(__VA_ARGS__)) #define __BOOST_DI_TYPE_WKND(T) (T &&) #define __BOOST_DI_ACCESS_WKND public #define __BOOST_DI_VARIABLE_TEMPLATE_INIT_WKND #endif #if !defined(__has_builtin) #define __has_builtin(...) 0 #endif #if !defined(__has_extension) #define __has_extension(...) 0 #endif #if defined(__CLANG__) #if (!BOOST_DI_CFG_DIAGNOSTICS_LEVEL) #pragma clang diagnostic error "-Wdeprecated-declarations" #else #pragma clang diagnostic warning "-Wdeprecated-declarations" #endif #pragma clang diagnostic push #pragma clang diagnostic error "-Wundefined-inline" #pragma clang diagnostic error "-Wundefined-internal" #pragma clang diagnostic ignored "-Wmissing-field-initializers" #elif defined(__GCC__) #pragma GCC diagnostic push #pragma GCC diagnostic error "-Wdeprecated-declarations" #if (__GNUC__ < 6) #pragma GCC diagnostic error "-Werror" #endif #elif defined(__MSVC__) #pragma warning(disable : 4503) #pragma warning(disable : 4822) #pragma warning(disable : 4505) #endif #if defined(_LIBCPP_VERSION) #define NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD { #else #define NAMESPACE_STD_BEGIN namespace std { #endif #if defined(_LIBCPP_VERSION) #define NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD #else #define NAMESPACE_STD_END } #endif #if __has_include(<__config>) #include <__config> #endif #if __has_include(<memory>) #include <memory> #else NAMESPACE_STD_BEGIN template <class> class shared_ptr; template <class> class weak_ptr; template <class, class> class unique_ptr; NAMESPACE_STD_END #endif #if __has_include(<vector>) #include <vector> #else NAMESPACE_STD_BEGIN template <class, class> class vector; NAMESPACE_STD_END #endif #if __has_include(<set>) #include <set> #else NAMESPACE_STD_BEGIN template <class, class, class> class set; NAMESPACE_STD_END #endif #if __has_include(<initializer_list>) #include <initializer_list> #else NAMESPACE_STD_BEGIN template <class> class initializer_list; NAMESPACE_STD_END #endif #if __has_include(<tuple>) #include <tuple> #else NAMESPACE_STD_BEGIN template <class...> class tuple; NAMESPACE_STD_END #endif #if __has_include(<iterator>) #include <iterator> #else NAMESPACE_STD_BEGIN template <class> class move_iterator; NAMESPACE_STD_END #endif #if __has_include(<string>) #include <string> #else NAMESPACE_STD_BEGIN template <class> struct char_traits; NAMESPACE_STD_END #endif // clang-format off #if __has_include(<boost/shared_ptr.hpp>) // clang-format on #include <boost/shared_ptr.hpp> #else namespace boost { template <class> class shared_ptr; } #endif BOOST_DI_NAMESPACE_BEGIN struct _ { _(...) {} }; namespace aux { using swallow = int[]; template <class T> using owner = T; template <class...> struct valid { using type = int; }; template <class... Ts> using valid_t = typename valid<Ts...>::type; template <class...> struct type {}; struct none_type {}; template <class T, T> struct non_type {}; template <class...> struct always { static constexpr auto value = true; }; template <class...> struct never { static constexpr auto value = false; }; template <class T, class...> struct identity { using type = T; }; template <class...> struct type_list { using type = type_list; }; template <bool...> struct bool_list { using type = bool_list; }; template <class T1, class T2> struct pair { using type = pair; using first = T1; using second = T2; }; template <class... Ts> struct inherit : Ts... { using type = inherit; }; template <class... Ts> struct join { using type = type_list<>; }; template <class T> struct join<T> { using type = T; }; template <class... T1s, class... T2s, class... Ts> struct join<type_list<T1s...>, type_list<T2s...>, Ts...> : join<type_list<T1s..., T2s...>, Ts...> {}; template <class... Ts, class... T1s, class... T2s, class... T3s, class... T4s, class... T5s, class... T6s, class... T7s, class... T8s, class... T9s, class... T10s, class... T11s, class... T12s, class... T13s, class... T14s, class... T15s, class... T16s, class... Us> struct join<type_list<Ts...>, type_list<T1s...>, type_list<T2s...>, type_list<T3s...>, type_list<T4s...>, type_list<T5s...>, type_list<T6s...>, type_list<T7s...>, type_list<T8s...>, type_list<T9s...>, type_list<T10s...>, type_list<T11s...>, type_list<T12s...>, type_list<T13s...>, type_list<T14s...>, type_list<T15s...>, type_list<T16s...>, Us...> : join<type_list<Ts..., T1s..., T2s..., T3s..., T4s..., T5s..., T6s..., T7s..., T8s..., T9s..., T10s..., T11s..., T12s..., T13s..., T14s..., T15s..., T16s...>, Us...> {}; template <class... TArgs> using join_t = typename join<TArgs...>::type; template <int...> struct index_sequence { using type = index_sequence; }; #if defined(__cpp_lib_integer_sequence) && defined(__GNUC__) template <int... Ns> index_sequence<Ns...> from_std(std::integer_sequence<int, Ns...>) { return {}; } template <int N> using make_index_sequence = decltype(from_std(std::make_integer_sequence<int, N>{})); #else #if __has_builtin(__make_integer_seq) template <class T, T...> struct integer_sequence; template <int... Ns> struct integer_sequence<int, Ns...> { using type = index_sequence<Ns...>; }; template <int N> struct make_index_sequence_impl { using type = typename __make_integer_seq<integer_sequence, int, N>::type; }; #else template <int> struct make_index_sequence_impl; template <> struct make_index_sequence_impl<0> : index_sequence<> {}; template <> struct make_index_sequence_impl<1> : index_sequence<0> {}; template <> struct make_index_sequence_impl<2> : index_sequence<0, 1> {}; template <> struct make_index_sequence_impl<3> : index_sequence<0, 1, 2> {}; template <> struct make_index_sequence_impl<4> : index_sequence<0, 1, 2, 3> {}; template <> struct make_index_sequence_impl<5> : index_sequence<0, 1, 2, 3, 4> {}; template <> struct make_index_sequence_impl<6> : index_sequence<0, 1, 2, 3, 4, 5> {}; template <> struct make_index_sequence_impl<7> : index_sequence<0, 1, 2, 3, 4, 5, 6> {}; template <> struct make_index_sequence_impl<8> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7> {}; template <> struct make_index_sequence_impl<9> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7, 8> {}; template <> struct make_index_sequence_impl<10> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7, 8, 9> {}; #endif template <int N> using make_index_sequence = typename make_index_sequence_impl<N>::type; #endif } namespace placeholders { __BOOST_DI_UNUSED static const struct arg { } _{}; } template <class, class = void> struct named {}; struct no_name { constexpr auto operator()() const noexcept { return ""; } }; template <class, class = int> struct ctor_traits; template <class> struct self {}; struct ignore_policies {}; namespace core { template <class> struct any_type_fwd; template <class> struct any_type_ref_fwd; template <class> struct any_type_1st_fwd; template <class> struct any_type_1st_ref_fwd; struct dependency_base {}; struct injector_base {}; template <class T> struct dependency__ : T { using T::create; using T::is_referable; using T::try_create; }; template <class T> struct injector__ : T { using T::cfg; using T::create_impl; using T::create_successful_impl; #if defined(__MSVC__) template <class... Ts> using is_creatable = typename T::template is_creatable<Ts...>; template <class... Ts> using try_create = typename T::template try_create<Ts...>; #else using T::is_creatable; using T::try_create; #endif }; template <class, class...> struct array; struct deduced {}; struct none {}; template <class, class TExpected = deduced, class = TExpected, class = no_name, class = void, class = none> class dependency; } namespace scopes { class deduce; class instance; class singleton; class unique; } #define __BOOST_DI_REQUIRES(...) typename ::boost::di::v1_1_0::aux::enable_if<__VA_ARGS__, int>::type #define __BOOST_DI_REQUIRES_MSG(...) typename ::boost::di::v1_1_0::aux::concept_check<__VA_ARGS__>::type namespace aux { template <class T> T&& declval(); template <class T, T V> struct integral_constant { using type = integral_constant; static constexpr T value = V; }; using true_type = integral_constant<bool, true>; using false_type = integral_constant<bool, false>; template <bool B, class T, class F> struct conditional { using type = T; }; template <class T, class F> struct conditional<false, T, F> { using type = F; }; template <bool B, class T, class F> using conditional_t = typename conditional<B, T, F>::type; template <bool B, class T = void> struct enable_if {}; template <class T> struct enable_if<true, T> { using type = T; }; template <bool B, class T = void> using enable_if_t = typename enable_if<B, T>::type; template <class T> struct concept_check { static_assert(T::value, "constraint not satisfied"); }; template <> struct concept_check<true_type> { using type = int; }; template <class T> struct remove_reference { using type = T; }; template <class T> struct remove_reference<T&> { using type = T; }; template <class T> struct remove_reference<T&&> { using type = T; }; template <class T> using remove_reference_t = typename remove_reference<T>::type; template <class T> struct remove_pointer { using type = T; }; template <class T> struct remove_pointer<T*> { using type = T; }; template <class T> using remove_pointer_t = typename remove_pointer<T>::type; template <class T> struct remove_smart_ptr { using type = T; }; template <class T, class TDeleter> struct remove_smart_ptr<std::unique_ptr<T, TDeleter>> { using type = T; }; template <class T> struct remove_smart_ptr<std::shared_ptr<T>> { using type = T; }; template <class T> struct remove_smart_ptr<std::weak_ptr<T>> { using type = T; }; template <class T> struct remove_smart_ptr<boost::shared_ptr<T>> { using type = T; }; template <class T> using remove_smart_ptr_t = typename remove_smart_ptr<T>::type; template <class T> struct remove_qualifiers { using type = T; }; template <class T> struct remove_qualifiers<const T> { using type = T; }; template <class T> struct remove_qualifiers<T&> { using type = T; }; template <class T> struct remove_qualifiers<const T&> { using type = T; }; template <class T> struct remove_qualifiers<T*> { using type = T; }; template <class T> struct remove_qualifiers<const T*> { using type = T; }; template <class T> struct remove_qualifiers<T* const&> { using type = T; }; template <class T> struct remove_qualifiers<T* const> { using type = T; }; template <class T> struct remove_qualifiers<const T* const> { using type = T; }; template <class T> struct remove_qualifiers<T&&> { using type = T; }; template <class T> using remove_qualifiers_t = typename remove_qualifiers<T>::type; template <class T> struct remove_extent { using type = T; }; template <class T> struct remove_extent<T[]> { using type = T; }; template <class T> using remove_extent_t = typename remove_extent<T>::type; template <class T> struct deref_type { using type = T; }; template <class T, class TDeleter> struct deref_type<std::unique_ptr<T, TDeleter>> { using type = remove_qualifiers_t<typename deref_type<T>::type>; }; template <class T> struct deref_type<std::shared_ptr<T>> { using type = remove_qualifiers_t<typename deref_type<T>::type>; }; template <class T> struct deref_type<boost::shared_ptr<T>> { using type = remove_qualifiers_t<typename deref_type<T>::type>; }; template <class T> struct deref_type<std::weak_ptr<T>> { using type = remove_qualifiers_t<typename deref_type<T>::type>; }; template <class T, class TAllocator> struct deref_type<std::vector<T, TAllocator>> { using type = core::array<remove_qualifiers_t<typename deref_type<T>::type>>; }; template <class TKey, class TCompare, class TAllocator> struct deref_type<std::set<TKey, TCompare, TAllocator>> { using type = core::array<remove_qualifiers_t<typename deref_type<TKey>::type>>; }; template <class T> struct deref_type<std::initializer_list<T>> { using type = core::array<remove_qualifiers_t<typename deref_type<T>::type>>; }; template <class T> using decay_t = typename deref_type<remove_qualifiers_t<T>>::type; template <class, class> struct is_same : false_type {}; template <class T> struct is_same<T, T> : true_type {}; template <class T, class U> struct is_base_of : integral_constant<bool, __is_base_of(T, U)> {}; template <class T> struct is_class : integral_constant<bool, __is_class(T)> {}; template <class T> struct is_abstract : integral_constant<bool, __is_abstract(T)> {}; template <class T> struct is_polymorphic : integral_constant<bool, __is_polymorphic(T)> {}; template <class T> struct is_final : integral_constant<bool, __is_final(T)> {}; template <class...> using is_valid_expr = true_type; #if __has_extension(is_constructible) && !((__clang_major__ == 3) && (__clang_minor__ == 5)) template <class T, class... TArgs> using is_constructible = integral_constant<bool, __is_constructible(T, TArgs...)>; #else template <class T, class... TArgs> decltype(void(T(declval<TArgs>()...)), true_type{}) test_is_constructible(int); template <class, class...> false_type test_is_constructible(...); template <class T, class... TArgs> struct is_constructible : decltype(test_is_constructible<T, TArgs...>(0)) {}; #endif template <class T, class... TArgs> using is_constructible_t = typename is_constructible<T, TArgs...>::type; template <class T, class... TArgs> decltype(void(T{declval<TArgs>()...}), true_type{}) test_is_braces_constructible(int); template <class, class...> false_type test_is_braces_constructible(...); template <class T, class... TArgs> using is_braces_constructible = decltype(test_is_braces_constructible<T, TArgs...>(0)); template <class T, class... TArgs> using is_braces_constructible_t = typename is_braces_constructible<T, TArgs...>::type; #if defined(__MSVC__) template <class T> struct is_copy_constructible : integral_constant<bool, __is_constructible(T, const T&)> {}; template <class T> struct is_default_constructible : integral_constant<bool, __is_constructible(T)> {}; #else template <class T> using is_copy_constructible = is_constructible<T, const T&>; template <class T> using is_default_constructible = is_constructible<T>; #endif #if defined(__CLANG__) || defined(__MSVC__) template <class T, class U> struct is_convertible : integral_constant<bool, __is_convertible_to(T, U)> {}; #else struct test_is_convertible__ { template <class T> static void test(T); }; template <class T, class U, class = decltype(test_is_convertible__::test<U>(declval<T>()))> true_type test_is_convertible(int); template <class, class> false_type test_is_convertible(...); template <class T, class U> using is_convertible = decltype(test_is_convertible<T, U>(0)); #endif template <class TSrc, class TDst, class U = remove_qualifiers_t<TDst>> using is_narrowed = integral_constant<bool, !is_class<TSrc>::value && !is_class<U>::value && !is_same<TSrc, U>::value>; template <class, class...> struct is_array : false_type {}; template <class T, class... Ts> struct is_array<T[], Ts...> : true_type {}; template <class T, class = decltype(sizeof(T))> true_type is_complete_impl(int); template <class T> false_type is_complete_impl(...); template <class T> struct is_complete : decltype(is_complete_impl<T>(0)) {}; template <class T, class U, class = decltype(sizeof(U))> is_base_of<T, U> is_a_impl(int); template <class T, class U> false_type is_a_impl(...); template <class T, class U> struct is_a : decltype(is_a_impl<T, U>(0)) {}; template <class, class...> struct is_unique_impl; template <class...> struct not_unique : false_type { using type = not_unique; }; template <> struct not_unique<> : true_type { using type = not_unique; }; template <class T> struct is_unique_impl<T> : not_unique<> {}; template <class T1, class T2, class... Ts> struct is_unique_impl<T1, T2, Ts...> : conditional_t<is_base_of<type<T2>, T1>::value, not_unique<T2>, is_unique_impl<inherit<T1, type<T2>>, Ts...>> {}; template <class... Ts> using is_unique = is_unique_impl<none_type, Ts...>; template <class...> struct unique; template <class... Rs, class T, class... Ts> struct unique<type<Rs...>, T, Ts...> : conditional_t<is_base_of<type<T>, inherit<type<Rs>...>>::value, unique<type<Rs...>, Ts...>, unique<type<Rs..., T>, Ts...>> {}; template <class... Rs> struct unique<type<Rs...>> : type_list<Rs...> {}; template <class... Ts> using unique_t = typename unique<type<>, Ts...>::type; false_type has_shared_ptr__(...); #if !defined(BOOST_DI_DISABLE_SHARED_PTR_DEDUCTION) template <class T> auto has_shared_ptr__(T &&) -> is_valid_expr<decltype(std::shared_ptr<T>{})>; #endif template <class T, class... TArgs> decltype(::boost::di::v1_1_0::aux::declval<T>().operator()(::boost::di::v1_1_0::aux::declval<TArgs>()...), ::boost::di::v1_1_0::aux::true_type()) is_invocable_impl(int); template <class, class...> ::boost::di::v1_1_0::aux::false_type is_invocable_impl(...); template <class T, class... TArgs> struct is_invocable : decltype(is_invocable_impl<T, TArgs...>(0)) {}; struct callable_base_impl { void operator()(...) {} }; template <class T> struct callable_base : callable_base_impl, aux::conditional_t<aux::is_class<T>::value && !aux::is_final<T>::value, T, aux::none_type> {}; template <typename T> aux::false_type is_callable_impl(T*, aux::non_type<void (callable_base_impl::*)(...), &T::operator()>* = 0); aux::true_type is_callable_impl(...); template <class T> struct is_callable : decltype(is_callable_impl((callable_base<T>*)0)) {}; template <class, class = int> struct is_empty_expr : false_type {}; template <class TExpr> #if defined(__MSVC__) struct is_empty_expr<TExpr, valid_t<decltype(declval<TExpr>()())>> : integral_constant<bool, sizeof(TExpr) == 1> { }; #else struct is_empty_expr<TExpr, valid_t<decltype(+declval<TExpr>()), decltype(declval<TExpr>()())>> : true_type { }; #endif template <class> struct function_traits; template <class R, class... TArgs> struct function_traits<R (*)(TArgs...)> { using result_type = R; using args = type_list<TArgs...>; }; template <class R, class... TArgs> struct function_traits<R(TArgs...)> { using result_type = R; using args = type_list<TArgs...>; }; template <class R, class T, class... TArgs> struct function_traits<R (T::*)(TArgs...)> { using result_type = R; using args = type_list<TArgs...>; }; template <class R, class T, class... TArgs> struct function_traits<R (T::*)(TArgs...) const> { using result_type = R; using args = type_list<TArgs...>; }; template <class T> using function_traits_t = typename function_traits<T>::args; } namespace core { template <class T, class = typename aux::is_a<injector_base, T>::type> struct bindings_impl; template <class T> struct bindings_impl<T, aux::true_type> { using type = typename T::deps; }; template <class T> struct bindings_impl<T, aux::false_type> { using type = aux::type_list<T>; }; #if defined(__MSVC__) template <class... Ts> struct bindings : aux::join_t<typename bindings_impl<Ts>::type...> {}; template <class... Ts> using bindings_t = typename bindings<Ts...>::type; #else template <class... Ts> using bindings_t = aux::join_t<typename bindings_impl<Ts>::type...>; #endif } namespace concepts { template <class T, class...> struct type_ { template <class TName> struct named { struct is_bound_more_than_once : aux::false_type {}; }; struct is_bound_more_than_once : aux::false_type {}; struct is_neither_a_dependency_nor_an_injector : aux::false_type {}; struct has_disallowed_qualifiers : aux::false_type {}; struct is_abstract : #if (BOOST_DI_CFG_DIAGNOSTICS_LEVEL >= 2) // clang-format off decltype( T{} ), // clang-format on #endif aux::false_type { }; template <class> struct is_not_related_to : aux::false_type {}; }; template <class...> struct any_of : aux::false_type {}; template <class... TDeps> struct is_supported : aux::is_same<aux::bool_list<aux::always<TDeps>::value...>, aux::bool_list<(aux::is_constructible<TDeps, TDeps&&>::value && (aux::is_a<core::injector_base, TDeps>::value || aux::is_a<core::dependency_base, TDeps>::value || aux::is_empty_expr<TDeps>::value))...>> { }; template <class...> struct get_not_supported; template <class T> struct get_not_supported<T> { using type = T; }; template <class T, class... TDeps> struct get_not_supported<T, TDeps...> : aux::conditional<aux::is_a<core::injector_base, T>::value || aux::is_a<core::dependency_base, T>::value, typename get_not_supported<TDeps...>::type, T> {}; template <class> struct is_unique; template <class T, class = int> struct unique_dependency : aux::type<T> {}; template <class T> struct unique_dependency<T, __BOOST_DI_REQUIRES(aux::is_a<core::dependency_base, T>::value)> : aux::pair<aux::pair<typename T::expected, typename T::name>, typename T::priority> {}; template <class... TDeps> struct is_unique<aux::type_list<TDeps...>> : aux::is_unique<typename unique_dependency<TDeps>::type...> {}; template <class> struct get_is_unique_error_impl : aux::true_type {}; template <class T, class TName, class TPriority> struct get_is_unique_error_impl<aux::not_unique<aux::pair<aux::pair<T, TName>, TPriority>>> { using type = typename type_<T>::template named<TName>::is_bound_more_than_once; }; template <class T, class TPriority> struct get_is_unique_error_impl<aux::not_unique<aux::pair<aux::pair<T, no_name>, TPriority>>> { using type = typename type_<T>::is_bound_more_than_once; }; template <class T> struct get_is_unique_error_impl<aux::not_unique<T>> { using type = typename type_<T>::is_bound_more_than_once; }; template <class> struct get_is_unique_error; template <class... TDeps> struct get_is_unique_error<aux::type_list<TDeps...>> : get_is_unique_error_impl<typename aux::is_unique<typename unique_dependency<TDeps>::type...>::type> {}; template <class... TDeps> using boundable_bindings = aux::conditional_t<is_supported<TDeps...>::value, typename get_is_unique_error<core::bindings_t<TDeps...>>::type, typename type_<typename get_not_supported<TDeps...>::type>::is_neither_a_dependency_nor_an_injector>; template <class... Ts> struct get_any_of_error : aux::conditional<aux::is_same<aux::bool_list<aux::always<Ts>::value...>, aux::bool_list<aux::is_same<aux::true_type, Ts>::value...>>::value, aux::true_type, any_of<Ts...>> {}; template <bool, class...> struct is_related { static constexpr auto value = true; }; template <class I, class T> struct is_related<true, I, T> { static constexpr auto value = aux::is_base_of<I, T>::value || (aux::is_convertible<T, I>::value && !aux::is_narrowed<I, T>::value); }; template <bool, class> struct is_abstract { static constexpr auto value = false; }; template <class T> struct is_abstract<true, T> { static constexpr auto value = aux::is_abstract<T>::value; }; auto boundable_impl(any_of<> &&) -> aux::true_type; template <class T, class... Ts> auto boundable_impl(any_of<T, Ts...> &&) -> aux::conditional_t<aux::is_same<T, aux::decay_t<T>>::value, decltype(boundable_impl(aux::declval<any_of<Ts...>>())), typename type_<T>::has_disallowed_qualifiers>; template <class I, class T> using boundable_impl__ = aux::conditional_t< is_related<aux::is_complete<I>::value && aux::is_complete<T>::value, I, T>::value, aux::conditional_t<is_abstract<aux::is_complete<T>::value, T>::value, typename type_<T>::is_abstract, aux::true_type>, typename type_<T>::template is_not_related_to<I>>; template <class I, class T> auto boundable_impl(I&&, T &&) -> aux::conditional_t<aux::is_same<T, aux::decay_t<T>>::value || !aux::is_complete<I>::value, boundable_impl__<I, T>, typename type_<T>::has_disallowed_qualifiers>; template <class I, class T> auto boundable_impl(I&&, T&&, aux::valid<> &&) -> aux::conditional_t<is_related<aux::is_complete<I>::value && aux::is_complete<T>::value, I, T>::value, aux::true_type, typename type_<T>::template is_not_related_to<I>>; template <class I, class T> auto boundable_impl(I* [], T &&) -> aux::conditional_t<aux::is_same<I, aux::decay_t<I>>::value, boundable_impl__<I, T>, typename type_<I>::has_disallowed_qualifiers>; template <class I, class T> auto boundable_impl(I[], T &&) -> aux::conditional_t<aux::is_same<I, aux::decay_t<I>>::value, boundable_impl__<I, T>, typename type_<I>::has_disallowed_qualifiers>; template <class... TDeps> auto boundable_impl(aux::type_list<TDeps...> &&) -> boundable_bindings<TDeps...>; template <class T, class... Ts> auto boundable_impl(concepts::any_of<Ts...>&&, T &&) -> typename get_any_of_error<decltype(boundable_impl(aux::declval<Ts>(), aux::declval<T>()))...>::type; template <class... TDeps> auto boundable_impl(aux::type<TDeps...> &&) -> typename get_is_unique_error_impl<typename aux::is_unique<TDeps...>::type>::type; aux::true_type boundable_impl(...); template <class... Ts> struct boundable__ { using type = decltype(boundable_impl(aux::declval<Ts>()...)); }; template <class... Ts> using boundable = typename boundable__<Ts...>::type; } namespace type_traits { struct stack {}; struct heap {}; template <class T, class = int> struct memory_traits { using type = stack; }; template <class T> struct memory_traits<T*> { using type = heap; }; template <class T> struct memory_traits<const T&> { using type = typename memory_traits<T>::type; }; template <class T, class TDeleter> struct memory_traits<std::unique_ptr<T, TDeleter>> { using type = heap; }; template <class T> struct memory_traits<std::shared_ptr<T>> { using type = heap; }; template <class T> struct memory_traits<boost::shared_ptr<T>> { using type = heap; }; template <class T> struct memory_traits<std::weak_ptr<T>> { using type = heap; }; template <class T> struct memory_traits<T, __BOOST_DI_REQUIRES(aux::is_polymorphic<T>::value)> { using type = heap; }; } namespace concepts { template <class...> struct scope { struct is_referable {}; struct try_create {}; struct create {}; template <class...> struct requires_ : aux::false_type {}; }; template <class> struct scope__ { template <class...> struct scope { template <class...> using is_referable = aux::true_type; template <class T, class, class TProvider> T try_create(const TProvider&); template <class T, class, class TProvider> T create(const TProvider&); }; }; template <class> struct config__ { template <class T> struct scope_traits { using type = scope__<T>; }; template <class T> struct memory_traits { using type = type_traits::heap; }; }; template <class T> struct provider__ { using config = config__<T>; template <class TMemory = type_traits::heap> aux::conditional_t<aux::is_same<TMemory, type_traits::stack>::value, T, T*> try_get(const TMemory& = {}) const; template <class TMemory = type_traits::heap> T* get(const TMemory& = {}) const { return nullptr; } config& cfg() const; }; template <class T> typename scope<T>::template requires_<typename scope<_, _>::is_referable, typename scope<_, _>::try_create, typename scope<_, _>::create> scopable_impl(...); template <class T> auto scopable_impl(T &&) -> aux::is_valid_expr<typename T::template scope<_, _>::template is_referable<_, config__<_>>, decltype(T::template scope<_, _>::template try_create<_, _>(provider__<_>{})), decltype(aux::declval<typename T::template scope<_, _>>().template create<_, _>(provider__<_>{}))>; template <class T> struct scopable__ { using type = decltype(scopable_impl<T>(aux::declval<T>())); }; template <class T> using scopable = typename scopable__<T>::type; } namespace core { template <class = aux::type_list<>> struct pool; template <class... TArgs> using pool_t = pool<aux::type_list<TArgs...>>; template <class... TArgs> struct pool<aux::type_list<TArgs...>> : TArgs... { template <class... Ts> explicit pool(Ts... args) noexcept : Ts(static_cast<Ts&&>(args))... {} template <class... Ts, class TPool> pool(const aux::type_list<Ts...>&, TPool p) noexcept : pool(static_cast<Ts&&>(p)...) { (void)p; } template <class T> pool& operator=(T&& other) noexcept { (void)aux::swallow{0, (static_cast<TArgs&>(*this).operator=(static_cast<TArgs&&>(other)), 0)...}; return *this; } }; } #if !defined(BOOST_DI_CFG_CTOR_LIMIT_SIZE) #define BOOST_DI_CFG_CTOR_LIMIT_SIZE 10 #endif namespace type_traits { template <class, class = int> struct is_injectable : ::boost::di::v1_1_0::aux::false_type {}; template <class T> struct is_injectable<T, ::boost::di::v1_1_0::aux::valid_t<typename T::boost_di_inject__>> : ::boost::di::v1_1_0::aux::true_type {}; struct direct {}; struct uniform {}; template <class T, int> using get = T; template <template <class...> class, class, class, class = int> struct ctor_impl; template <template <class...> class TIsConstructible, class T> struct ctor_impl<TIsConstructible, T, aux::index_sequence<>> : aux::type_list<> {}; template <template <class...> class TIsConstructible, class T> struct ctor_impl<TIsConstructible, T, aux::index_sequence<0>, __BOOST_DI_REQUIRES(TIsConstructible<T, core::any_type_1st_fwd<T>>::value)> : aux::type_list<core::any_type_1st_fwd<T>> {}; template <template <class...> class TIsConstructible, class T> struct ctor_impl<TIsConstructible, T, aux::index_sequence<0>, __BOOST_DI_REQUIRES(!TIsConstructible<T, core::any_type_1st_fwd<T>>::value)> : aux::conditional_t<TIsConstructible<T, core::any_type_1st_ref_fwd<T>>::value, aux::type_list<core::any_type_1st_ref_fwd<T>>, aux::type_list<>> {}; template <template <class...> class TIsConstructible, class T, int... Ns> struct ctor_impl<TIsConstructible, T, aux::index_sequence<Ns...>, __BOOST_DI_REQUIRES((sizeof...(Ns) > 1) && TIsConstructible<T, get<core::any_type_fwd<T>, Ns>...>::value)> : aux::type_list<get<core::any_type_fwd<T>, Ns>...> {}; template <template <class...> class TIsConstructible, class T, int... Ns> struct ctor_impl<TIsConstructible, T, aux::index_sequence<Ns...>, __BOOST_DI_REQUIRES((sizeof...(Ns) > 1) && !TIsConstructible<T, get<core::any_type_fwd<T>, Ns>...>::value)> : aux::conditional<TIsConstructible<T, get<core::any_type_ref_fwd<T>, Ns>...>::value, aux::type_list<get<core::any_type_ref_fwd<T>, Ns>...>, typename ctor_impl<TIsConstructible, T, aux::make_index_sequence<sizeof...(Ns) - 1>>::type> {}; template <template <class...> class TIsConstructible, class T> using ctor_impl_t = typename ctor_impl<TIsConstructible, T, aux::make_index_sequence<BOOST_DI_CFG_CTOR_LIMIT_SIZE>>::type; template <class...> struct ctor; template <class T> struct ctor<T, aux::type_list<>> : aux::pair<uniform, ctor_impl_t<aux::is_braces_constructible, T>> {}; template <class T, class... TArgs> struct ctor<T, aux::type_list<TArgs...>> : aux::pair<direct, aux::type_list<TArgs...>> {}; template <class T, class, class = typename is_injectable<ctor_traits<T>>::type> struct ctor_traits_impl; template <class T, class = void, class = void, class = typename is_injectable<T>::type> struct ctor_traits__; template <class T, class _1, class _2> struct ctor_traits__<T, _1, _2, aux::true_type> : aux::pair<T, aux::pair<direct, typename T::boost_di_inject__::type>> {}; template <class T, class _1, class _2> struct ctor_traits__<T, _1, _2, aux::false_type> : ctor_traits_impl<T, _1> {}; template <class T, class _1, class... Ts> struct ctor_traits__<T, _1, core::pool_t<Ts...>, aux::false_type> : aux::pair<T, aux::pair<uniform, aux::type_list<Ts...>>> {}; template <class T, class _> struct ctor_traits_impl<T, _, aux::true_type> : aux::pair<T, aux::pair<direct, typename ctor_traits<T>::boost_di_inject__::type>> {}; template <class T, class _> struct ctor_traits_impl<T, _, aux::false_type> : aux::pair<T, typename ctor_traits<T>::type> {}; } template <class T, class> struct ctor_traits : type_traits::ctor<T, type_traits::ctor_impl_t<aux::is_constructible, T>> {}; template <class T> struct ctor_traits<std::initializer_list<T>> { using boost_di_inject__ = aux::type_list<>; }; template <class... Ts> struct ctor_traits<std::tuple<Ts...>> { using boost_di_inject__ = aux::type_list<Ts...>; }; template <class T> struct ctor_traits<T, __BOOST_DI_REQUIRES(aux::is_same<std::char_traits<char>, typename T::traits_type>::value)> { using boost_di_inject__ = aux::type_list<>; }; template <class T> struct ctor_traits<T, __BOOST_DI_REQUIRES(!aux::is_class<T>::value)> { using boost_di_inject__ = aux::type_list<>; }; namespace type_traits { template <class T> struct remove_named { using type = T; }; template <class TName, class T> struct remove_named<named<TName, T>> { using type = T; }; template <class T> using remove_named_t = typename remove_named<T>::type; template <class T> struct add_named { using type = named<no_name, T>; }; template <class TName, class T> struct add_named<named<TName, T>> { using type = named<TName, T>; }; template <class T> using add_named_t = typename add_named<T>::type; template <class T> struct named_decay { using type = aux::decay_t<T>; }; template <class TName, class T> struct named_decay<named<TName, T>> { using type = named<TName, aux::decay_t<T>>; }; template <class T> using named_decay_t = typename named_decay<T>::type; } namespace type_traits { template <class, class T> struct rebind_traits { using type = T; }; template <class T, class TName, class _> struct rebind_traits<T, named<TName, _>> { using type = named<TName, T>; }; template <class T, class D, class U> struct rebind_traits<std::unique_ptr<T, D>, U> { using type = std::unique_ptr<U, D>; }; template <class T, class D, class TName, class _> struct rebind_traits<std::unique_ptr<T, D>, named<TName, _>> { using type = named<TName, std::unique_ptr<T, D>>; }; template <class T, class U> struct rebind_traits<std::shared_ptr<T>, U> { using type = std::shared_ptr<U>; }; template <class T, class TName, class _> struct rebind_traits<std::shared_ptr<T>, named<TName, _>> { using type = named<TName, std::shared_ptr<T>>; }; template <class T, class U> struct rebind_traits<std::weak_ptr<T>, U> { using type = std::weak_ptr<U>; }; template <class T, class TName, class _> struct rebind_traits<std::weak_ptr<T>, named<TName, _>> { using type = named<TName, std::weak_ptr<T>>; }; template <class T, class U> struct rebind_traits<boost::shared_ptr<T>, U> { using type = boost::shared_ptr<U>; }; template <class T, class TName, class _> struct rebind_traits<boost::shared_ptr<T>, named<TName, _>> { using type = named<TName, boost::shared_ptr<T>>; }; template <class T, class U> using rebind_traits_t = typename rebind_traits<T, U>::type; } namespace core { template <class T, class... Ts> struct array_impl : _ { using boost_di_inject__ = aux::type_list<Ts...>; explicit array_impl(type_traits::remove_named_t<Ts>&&... args) : array{static_cast<type_traits::remove_named_t<Ts>&&>(args)...} {} T array[sizeof...(Ts)]; }; template <class T, class... Ts> struct array<T(), Ts...> : T { using value_type = typename aux::identity<T>::type::value_type; using array_t = array_impl<value_type, type_traits::rebind_traits_t<value_type, Ts>...>; using boost_di_inject__ = aux::type_list<array_t&&>; template <__BOOST_DI_REQUIRES( aux::is_constructible<T, std::move_iterator<value_type*>, std::move_iterator<value_type*>>::value) = 0> explicit array(array_t&& a) : T(std::move_iterator<value_type*>(a.array), std::move_iterator<value_type*>(a.array + sizeof...(Ts))) {} }; template <class T> struct array<T()> : T { using boost_di_inject__ = aux::type_list<>; }; template <class T> struct array<T> {}; } namespace type_traits { template <class _, class T, class _1, class... Ts> struct ctor_traits__<core::array<_, Ts...>, T, _1, aux::false_type> : type_traits::ctor_traits__<core::array<aux::remove_smart_ptr_t<aux::remove_qualifiers_t<T>>(), Ts...>> {}; } namespace scopes { class deduce { public: template <class TExpected, class TGiven> class scope { public: template <class T, class TConfig> using is_referable = typename TConfig::template scope_traits<T>::type::template scope<TExpected, TGiven>::template is_referable<T, TConfig>; template <class T, class TName, class TProvider> static decltype(typename TProvider::config::template scope_traits<T>::type::template scope<TExpected, TGiven>{} .template try_create<T, TName>(aux::declval<TProvider>())) try_create(const TProvider&); template <class T, class TName, class TProvider> auto create(const TProvider& provider) { using scope_traits = typename TProvider::config::template scope_traits<T>::type; using scope = typename scope_traits::template scope<TExpected, TGiven>; return scope{}.template create<T, TName>(provider); } }; }; } static constexpr __BOOST_DI_UNUSED scopes::deduce deduce{}; namespace concepts { template <class T> struct abstract_type { struct is_not_bound { operator T*() const { using constraint_not_satisfied = is_not_bound; return constraint_not_satisfied{}.error(); } // clang-format off static inline T* error(_ = "type is not bound, did you forget to add: 'di::bind<interface>.to<implementation>()'?"); // clang-format on }; template <class TName> struct named { struct is_not_bound { operator T*() const { using constraint_not_satisfied = is_not_bound; return constraint_not_satisfied{}.error(); } // clang-format off static inline T* error(_ = "type is not bound, did you forget to add: 'di::bind<interface>.named(name).to<implementation>()'?"); // clang-format on }; }; }; template <class TScope, class T> struct scoped { template <class To> struct is_not_convertible_to { operator To() const { using constraint_not_satisfied = is_not_convertible_to; return constraint_not_satisfied{}.error(); } // clang-format off static inline To error(_ = "scoped object is not convertible to the requested type, did you mistake the scope: 'di::bind<T>.in(scope)'?"); // clang-format on }; }; template <class T> struct scoped<scopes::instance, T> { template <class To> struct is_not_convertible_to { operator To() const { using constraint_not_satisfied = is_not_convertible_to; return constraint_not_satisfied{}.error(); } // clang-format off static inline To error(_ = "instance is not convertible to the requested type, verify binding: 'di::bind<T>.to(value)'?"); // clang-format on }; }; template <class T> struct type { struct has_ambiguous_number_of_constructor_parameters { template <int Given> struct given { template <int Expected> struct expected { operator T*() const { using constraint_not_satisfied = expected; return constraint_not_satisfied{}.error(); } // clang-format off static inline T* error(_ = "verify BOOST_DI_INJECT_TRAITS or di::ctor_traits"); // clang-format on }; }; }; struct has_to_many_constructor_parameters { template <int TMax> struct max { operator T*() const { using constraint_not_satisfied = max; return constraint_not_satisfied{}.error(); } // clang-format off static inline T* error(_ = "increase BOOST_DI_CFG_CTOR_LIMIT_SIZE value or reduce number of constructor parameters"); // clang-format on }; }; struct is_not_exposed { operator T() const { using constraint_not_satisfied = is_not_exposed; return constraint_not_satisfied{}.error(); } // clang-format off static inline T error(_ = "type is not exposed, did you forget to add: 'di::injector<T>'?"); // clang-format on }; template <class TName> struct named { struct is_not_exposed { operator T() const { using constraint_not_satisfied = is_not_exposed; return constraint_not_satisfied{}.error(); } // clang-format off static inline T error(_ = "type is not exposed, did you forget to add: 'di::injector<BOOST_DI_EXPOSE((named = name)T)>'?"); // clang-format on }; }; }; template <class> struct ctor_size; template <class TInit, class... TCtor> struct ctor_size<aux::pair<TInit, aux::type_list<TCtor...>>> : aux::integral_constant<int, sizeof...(TCtor)> {}; template <class... TCtor> struct ctor_size<aux::type_list<TCtor...>> : aux::integral_constant<int, sizeof...(TCtor)> {}; template <class T> using ctor_size_t = ctor_size<typename type_traits::ctor<T, type_traits::ctor_impl_t<aux::is_constructible, T>>::type>; template <class TInitialization, class TName, class _, class TCtor, class T = aux::decay_t<_>> struct creatable_error_impl : aux::conditional_t< aux::is_polymorphic<T>::value, aux::conditional_t<aux::is_same<TName, no_name>::value, typename abstract_type<T>::is_not_bound, typename abstract_type<T>::template named<TName>::is_not_bound>, aux::conditional_t<ctor_size_t<T>::value == ctor_size<TCtor>::value, typename type<T>::has_to_many_constructor_parameters::template max<BOOST_DI_CFG_CTOR_LIMIT_SIZE>, typename type<T>::has_ambiguous_number_of_constructor_parameters::template given< ctor_size<TCtor>::value>::template expected<ctor_size_t<T>::value>>> {}; template <class TInit, class T, class... TArgs> struct creatable { static constexpr auto value = aux::is_constructible<T, TArgs...>::value; }; template <class T, class... TArgs> struct creatable<type_traits::uniform, T, TArgs...> { static constexpr auto value = aux::is_braces_constructible<T, TArgs...>::value; }; template <class TInitialization, class TName, class T, class... TArgs> T creatable_error() { return creatable_error_impl<TInitialization, TName, T, aux::type_list<TArgs...>>{}; } } namespace wrappers { template <class TScope, class T, class TObject = std::shared_ptr<T>> struct shared { using scope = TScope; template <class> struct is_referable_impl : aux::true_type {}; template <class I> struct is_referable_impl<std::shared_ptr<I>> : aux::is_same<I, T> {}; template <class I> struct is_referable_impl<boost::shared_ptr<I>> : aux::false_type {}; template <class T_> using is_referable = is_referable_impl<aux::remove_qualifiers_t<T_>>; template <class I, __BOOST_DI_REQUIRES(aux::is_convertible<T*, I*>::value) = 0> inline operator std::shared_ptr<I>() const noexcept { return object; } inline operator std::shared_ptr<T>&() noexcept { return object; } template <class I, __BOOST_DI_REQUIRES(aux::is_convertible<T*, I*>::value) = 0> inline operator boost::shared_ptr<I>() const noexcept { struct sp_holder { std::shared_ptr<T> object; void operator()(...) noexcept { object.reset(); } }; return {object.get(), sp_holder{object}}; } template <class I, __BOOST_DI_REQUIRES(aux::is_convertible<T*, I*>::value) = 0> inline operator std::weak_ptr<I>() const noexcept { return object; } inline operator T&() noexcept { return *object; } inline operator const T&() const noexcept { return *object; } TObject object; }; template <class TScope, class T> struct shared<TScope, T&> { using scope = TScope; template <class> struct is_referable : aux::true_type {}; explicit shared(T& object) : object(&object) {} template <class I> explicit shared(I); template <class I, __BOOST_DI_REQUIRES(aux::is_convertible<T, I>::value) = 0> inline operator I() const noexcept { return *object; } inline operator T&() const noexcept { return *object; } T* object = nullptr; }; } namespace wrappers { template <class TScope, class T> struct unique { using scope = TScope; template <class I, __BOOST_DI_REQUIRES(aux::is_convertible<T, I>::value) = 0> inline operator I() const noexcept { return object; } inline operator T &&() noexcept { return static_cast<T&&>(object); } T object; }; template <class TScope, class T> struct unique<TScope, T*> { using scope = TScope; #if defined(__MSVC__) explicit unique(T* object) : object(object) {} #endif template <class I, __BOOST_DI_REQUIRES(aux::is_convertible<T, I>::value) = 0> inline operator I() const noexcept { struct scoped_ptr { aux::owner<T*> ptr; ~scoped_ptr() noexcept { delete ptr; } }; return static_cast<T&&>(*scoped_ptr{object}.ptr); } template <class I, __BOOST_DI_REQUIRES(aux::is_convertible<T*, I*>::value) = 0> inline operator aux::owner<I*>() const noexcept { return object; } template <class I, __BOOST_DI_REQUIRES(aux::is_convertible<T*, const I*>::value) = 0> inline operator aux::owner<const I*>() const noexcept { return object; } template <class I, __BOOST_DI_REQUIRES(aux::is_convertible<T*, I*>::value) = 0> inline operator std::shared_ptr<I>() const noexcept { return std::shared_ptr<I>{object}; } template <class I, __BOOST_DI_REQUIRES(aux::is_convertible<T*, I*>::value) = 0> inline operator boost::shared_ptr<I>() const noexcept { return boost::shared_ptr<I>{object}; } template <class I, class D, __BOOST_DI_REQUIRES(aux::is_convertible<T*, I*>::value) = 0> inline operator std::unique_ptr<I, D>() const noexcept { return std::unique_ptr<I, D>{object}; } T* object = nullptr; }; } namespace scopes { class instance; namespace detail { template <class T, class TExpected, class TGiven> struct arg { using type = T; using expected = TExpected; using given = TGiven; }; template <class T> struct wrapper_traits { using type = wrappers::unique<instance, T>; }; template <class T> struct wrapper_traits<std::shared_ptr<T>> { using type = wrappers::shared<instance, T>; }; template <class T> using wrapper_traits_t = typename wrapper_traits<T>::type; template <class, class = int> struct has_result_type : ::boost::di::v1_1_0::aux::false_type {}; template <class T> struct has_result_type<T, ::boost::di::v1_1_0::aux::valid_t<typename T::result_type>> : ::boost::di::v1_1_0::aux::true_type {}; template <class TGiven, class TProvider, class... Ts> struct is_expr : aux::integral_constant< bool, aux::is_invocable<TGiven, typename TProvider::injector, Ts...>::value && !has_result_type<TGiven>::value> {}; } template <class T> struct wrapper { inline operator T() noexcept { return static_cast<T&&>(object); } T object; }; class instance { public: template <class, class TGiven, class = int> struct scope { template <class...> using is_referable = aux::false_type; explicit scope(const TGiven& object) : object_{object} {} template <class, class, class TProvider> static wrappers::unique<instance, TGiven> try_create(const TProvider&); template <class, class, class TProvider> auto create(const TProvider&) const noexcept { return wrappers::unique<instance, TGiven>{object_}; } TGiven object_; }; template <class TExpected, class TGiven> struct scope<TExpected, std::shared_ptr<TGiven>> { template <class T, class> using is_referable = typename wrappers::shared<instance, TGiven>::template is_referable<aux::remove_qualifiers_t<T>>; explicit scope(const std::shared_ptr<TGiven>& object) : object_{object} {} template <class, class, class TProvider> static wrappers::shared<instance, TGiven> try_create(const TProvider&); template <class, class, class TProvider> auto create(const TProvider&) const noexcept { return wrappers::shared<instance, TGiven>{object_}; } std::shared_ptr<TGiven> object_; }; template <class TExpected, class TGiven> struct scope<TExpected, std::initializer_list<TGiven>> { template <class...> using is_referable = aux::false_type; scope(const std::initializer_list<TGiven>& object) : object_(object) {} template <class, class, class TProvider> static std::initializer_list<TGiven> try_create(const TProvider&); template <class, class, class TProvider> auto create(const TProvider&) const noexcept { return wrappers::unique<instance, std::initializer_list<TGiven>>{object_}; } std::initializer_list<TGiven> object_; }; template <class TExpected, class TGiven> struct scope<TExpected, TGiven&, __BOOST_DI_REQUIRES(!aux::is_callable<TGiven>::value)> { template <class...> using is_referable = aux::true_type; explicit scope(TGiven& object) : object_{object} {} template <class, class, class TProvider> static wrappers::shared<instance, TGiven&> try_create(const TProvider&); template <class, class, class TProvider> auto create(const TProvider&) const noexcept { return object_; } wrappers::shared<instance, TGiven&> object_; }; template <class TExpected, class TGiven> struct scope<TExpected, TGiven, __BOOST_DI_REQUIRES(aux::is_callable<TGiven>::value)> { template <class...> using is_referable = aux::integral_constant<bool, !aux::is_callable<TExpected>::value || !detail::has_result_type<TExpected>::value>; explicit scope(const TGiven& object) : object_(object) {} #if defined(__MSVC__) template <class T, class, class TProvider> static T try_create(const TProvider&) noexcept; #else template <class, class, class TProvider, __BOOST_DI_REQUIRES(!detail::is_expr<TGiven, TProvider>::value && aux::is_callable<TGiven>::value && aux::is_callable<TExpected>::value) = 0> static wrappers::unique<instance, TExpected> try_create(const TProvider&) noexcept; template <class T, class, class TProvider, __BOOST_DI_REQUIRES(!detail::is_expr<TGiven, TProvider>::value && aux::is_invocable<TGiven>::value && !aux::is_callable<TExpected>::value) = 0> static auto try_create(const TProvider&) noexcept -> detail::wrapper_traits_t<decltype(aux::declval<typename aux::identity<TGiven, T>::type>()())>; template <class, class, class TProvider, __BOOST_DI_REQUIRES(detail::is_expr<TGiven, TProvider>::value) = 0> static detail::wrapper_traits_t<decltype(aux::declval<TGiven>()(aux::declval<typename TProvider::injector>()))> try_create( const TProvider&) noexcept; template <class T, class, class TProvider, __BOOST_DI_REQUIRES(detail::is_expr<TGiven, TProvider, const detail::arg<T, TExpected, TGiven>&>::value) = 0> static detail::wrapper_traits_t<decltype(aux::declval<TGiven>()(aux::declval<typename TProvider::injector>(), aux::declval<detail::arg<T, TExpected, TGiven>>()))> try_create(const TProvider&) noexcept; #endif template <class, class, class TProvider, __BOOST_DI_REQUIRES(!detail::is_expr<TGiven, TProvider>::value && aux::is_callable<TGiven>::value && aux::is_callable<TExpected>::value) = 0> auto create(const TProvider&) const noexcept { return wrappers::unique<instance, TExpected>{object_}; } template <class T, class, class TProvider, __BOOST_DI_REQUIRES(!detail::is_expr<TGiven, TProvider>::value && aux::is_invocable<TGiven>::value && !aux::is_callable<TExpected>::value) = 0> auto create(const TProvider&) const { using wrapper = detail::wrapper_traits_t<decltype(aux::declval<TGiven>()())>; return wrapper{object_()}; } template <class, class, class TProvider, __BOOST_DI_REQUIRES(detail::is_expr<TGiven, TProvider>::value) = 0> auto create(const TProvider& provider) { using wrapper = detail::wrapper_traits_t<decltype((object_)(provider.super()))>; return wrapper{(object_)(provider.super())}; } template <class T, class, class TProvider, __BOOST_DI_REQUIRES(detail::is_expr<TGiven, TProvider, const detail::arg<T, TExpected, TGiven>&>::value) = 0> auto create(const TProvider& provider) { using wrapper = detail::wrapper_traits_t<decltype((object_)(provider.super(), detail::arg<T, TExpected, TGiven>{}))>; return wrapper{(object_)(provider.super(), detail::arg<T, TExpected, TGiven>{})}; } TGiven object_; }; template <class _, class... Ts> class scope<_, aux::type_list<Ts...>> { template <class> struct injector__; template <class TName, class T> struct injector__<named<TName, T>> { T (*f)(const injector__*) = nullptr; explicit injector__(const decltype(f) & ptr) : f(ptr) {} }; struct injector : injector__<Ts>... { void (*dtor)(injector*) = nullptr; ~injector() noexcept { static_cast<injector*>(this)->dtor(this); } template <class TName, class T> T create(const named<TName, T>&, const aux::true_type&) const { return static_cast<const injector__<named<TName, T>>*>(this)->f(static_cast<const injector__<named<TName, T>>*>(this)); } template <class T> T create(const named<no_name, T>&, const aux::false_type&) const { return typename concepts::type<T>::is_not_exposed{}; } template <class TName, class T> T create(const named<TName, T>&, const aux::false_type&) const { return typename concepts::type<T>::template named<TName>::is_not_exposed{}; } }; template <class TInjector> class injector_impl : injector__<Ts>... { void (*dtor)(injector_impl*) = nullptr; static void dtor_impl(injector_impl* object) { object->~injector_impl(); } template <class, class> struct create; template <class TName, class T> struct create<named<TName, T>, aux::true_type> { static T impl(const injector__<named<TName, T>>* object) { using type = aux::type<aux::conditional_t<aux::is_same<TName, no_name>::value, T, named<TName, T>>>; return static_cast<const core::injector__<TInjector>&>(static_cast<const injector_impl*>(object)->injector_) .create_successful_impl(type{}); } }; template <class TName, class T> struct create<named<TName, T>, aux::false_type> { static T impl(const injector__<named<TName, T>>* object) { using type = aux::type<aux::conditional_t<aux::is_same<TName, no_name>::value, T, named<TName, T>>>; return static_cast<const core::injector__<TInjector>&>(static_cast<const injector_impl*>(object)->injector_) .create_impl(type{}); } }; template <class T> struct is_creatable : aux::integral_constant<bool, core::injector__<TInjector>::template is_creatable<T>::value> {}; template <class TName, class T> struct is_creatable<named<TName, T>> : aux::integral_constant<bool, core::injector__<TInjector>::template is_creatable<T, TName>::value> {}; public: explicit injector_impl(TInjector&& injector) noexcept : injector__<Ts>(&injector_impl::template create<Ts, typename is_creatable<Ts>::type>::impl)..., dtor(&injector_impl::dtor_impl), injector_(static_cast<TInjector&&>(injector)) {} private: TInjector injector_; }; public: template <class...> using is_referable = aux::true_type; template <class TInjector, __BOOST_DI_REQUIRES(aux::is_a<core::injector_base, TInjector>::value) = 0> explicit scope(TInjector&& i) noexcept : injector_((injector*)new injector_impl<TInjector>{static_cast<TInjector&&>(i)}) {} scope(scope&& other) noexcept : injector_(other.injector_) { other.injector_ = nullptr; } ~scope() noexcept { delete injector_; } template <class T, class TName, class TProvider> static aux::conditional_t<aux::is_base_of<injector__<named<TName, T>>, injector>::value, T, void> try_create( const TProvider&); template <class T, class TName, class TProvider> auto create(const TProvider&) { return wrapper<T>{injector_->create(named<TName, T>{}, aux::is_base_of<injector__<named<TName, T>>, injector>{})}; } private: injector* injector_; }; }; } namespace core { template <class, int, class T> struct ctor_arg { explicit ctor_arg(T&& t) : value(static_cast<T&&>(t)) {} constexpr operator T() const { return value; } private: T value; }; template <class, class> struct dependency_concept {}; template <class T, class TDependency> struct dependency_impl : aux::pair<T, TDependency> {}; template <class T> struct make_dependency_concept { using type = dependency_concept<T, no_name>; }; template <class TName, class T> struct make_dependency_concept<named<TName, T>> { using type = dependency_concept<T, TName>; }; template <class... Ts, class TName, class TDependency> struct dependency_impl<dependency_concept<concepts::any_of<Ts...>, TName>, TDependency> : aux::pair<dependency_concept<Ts, TName>, TDependency>... {}; template <class... Ts, class TDependency> struct dependency_impl<dependency_concept<aux::type_list<Ts...>, no_name>, TDependency> : aux::pair<typename make_dependency_concept<Ts>::type, TDependency>... {}; struct override {}; template <class TScope, class TExpected, class TGiven, class TName, class TPriority, class TCtor> class dependency : dependency_base, public TScope::template scope<TExpected, TGiven>, public dependency_impl<dependency_concept<TExpected, TName>, dependency<TScope, TExpected, TGiven, TName, TPriority, TCtor>>, protected TCtor { template <class, class, class, class, class, class> friend class dependency; using scope_t = typename TScope::template scope<TExpected, TGiven>; template <class T> using externable = aux::integral_constant< bool, aux::always<T>::value && aux::is_same<TScope, scopes::deduce>::value && aux::is_same<TExpected, TGiven>::value>; template <class T> struct ref_traits { using type = T; }; template <int N> struct ref_traits<const char (&)[N]> { using type = TExpected; }; template <class R, class... Ts> struct ref_traits<R (&)(Ts...)> { using type = TExpected; }; template <class T> struct ref_traits<std::shared_ptr<T>&> { using type = std::shared_ptr<T>; }; template <class T, class> struct deduce_traits { using type = T; }; template <class T> struct deduce_traits<deduced, T> { using type = aux::decay_t<T>; }; template <class T, class U> using deduce_traits_t = typename deduce_traits<T, U>::type; template <class TParent, int N, class T> using ctor_arg_traits = ctor_arg<TParent, N, T>; public: using scope = TScope; using expected = TExpected; using given = TGiven; using name = TName; using priority = TPriority; using ctor = TCtor; dependency() noexcept {} template <class T> explicit dependency(T&& object) noexcept : scope_t(static_cast<T&&>(object)) {} explicit dependency(TCtor&& ctor) noexcept : TCtor{static_cast<TCtor&&>(ctor)} {} template <class T, __BOOST_DI_REQUIRES(aux::is_same<TName, no_name>::value && !aux::is_same<T, no_name>::value) = 0> auto named() noexcept { return dependency<TScope, TExpected, TGiven, T, TPriority, TCtor>{static_cast<dependency&&>(*this)}; } template <class T, __BOOST_DI_REQUIRES(aux::is_same<TName, no_name>::value && !aux::is_same<T, no_name>::value) = 0> auto named(const T&) noexcept { return dependency<TScope, TExpected, TGiven, T, TPriority, TCtor>{static_cast<dependency&&>(*this)}; } template <class T, __BOOST_DI_REQUIRES_MSG(concepts::scopable<T>) = 0> auto in(const T&)noexcept { return dependency<T, TExpected, TGiven, TName, TPriority, TCtor>{}; } template <class T, __BOOST_DI_REQUIRES(!aux::is_array<TExpected, T>::value) = 0, __BOOST_DI_REQUIRES_MSG(concepts::boundable<TExpected, T>) = 0> auto to() noexcept { return dependency<TScope, TExpected, T, TName, TPriority, TCtor>{}; } template <class... Ts, __BOOST_DI_REQUIRES(aux::is_array<TExpected, Ts...>::value) = 0> auto to() noexcept { using type = aux::remove_pointer_t<aux::remove_extent_t<TExpected>>; return dependency<TScope, array<type>, array<type, Ts...>, TName, TPriority, TCtor>{}; } template <class T, __BOOST_DI_REQUIRES_MSG(concepts::boundable<TExpected, T>) = 0> auto to(std::initializer_list<T> il) noexcept { using type = aux::remove_pointer_t<aux::remove_extent_t<TExpected>>; using dependency = dependency<scopes::instance, array<type>, std::initializer_list<T>, TName, TPriority, TCtor>; return dependency{il}; } template <class T, __BOOST_DI_REQUIRES(externable<T>::value && !aux::is_callable<T>::value) = 0, __BOOST_DI_REQUIRES_MSG(concepts::boundable<deduce_traits_t<TExpected, T>, aux::decay_t<T>, aux::valid<>>) = 0> auto to(T&& object) noexcept { using dependency = dependency<scopes::instance, deduce_traits_t<TExpected, T>, typename ref_traits<T>::type, TName, TPriority, TCtor>; return dependency{static_cast<T&&>(object)}; } template <class T, __BOOST_DI_REQUIRES(externable<T>::value&& aux::is_callable<T>::value) = 0> auto to(T&& object) noexcept { using dependency = dependency<scopes::instance, deduce_traits_t<TExpected, T>, typename ref_traits<T>::type, TName, TPriority, TCtor>; return dependency{static_cast<T&&>(object)}; } template <class TConcept, class T, __BOOST_DI_REQUIRES(externable<T>::value && !aux::is_callable<T>::value) = 0, __BOOST_DI_REQUIRES_MSG(concepts::boundable<deduce_traits_t<TExpected, T>, aux::decay_t<T>, aux::valid<>>) = 0> auto to(T&& object) noexcept { using dependency = dependency<scopes::instance, deduce_traits_t<concepts::any_of<TExpected, TConcept>, T>, typename ref_traits<T>::type, TName, TPriority, TCtor>; return dependency{static_cast<T&&>(object)}; } template <class TConcept, class T, __BOOST_DI_REQUIRES(externable<T>::value&& aux::is_callable<T>::value) = 0> auto to(T&& object) noexcept { using dependency = dependency<scopes::instance, deduce_traits_t<concepts::any_of<TExpected, TConcept>, T>, typename ref_traits<T>::type, TName, TPriority, TCtor>; return dependency{static_cast<T&&>(object)}; } template <class T, class... Ts, __BOOST_DI_REQUIRES(!aux::is_array<TExpected, T>::value) = 0> auto to(Ts&&... args) noexcept { return to_impl<T>(aux::make_index_sequence<sizeof...(Ts)>{}, static_cast<Ts&&>(args)...); } template <template <class...> class T> auto to() noexcept { return dependency<TScope, TExpected, aux::identity<T<>>, TName, TPriority, TCtor>{}; } template <class...> dependency& to(...) const noexcept; auto operator[](const override&) noexcept { return dependency<TScope, TExpected, TGiven, TName, override>{static_cast<dependency&&>(*this)}; } #if defined(__cpp_variable_templates) dependency& operator()() noexcept { return *this; } #endif template <class... Ts, __BOOST_DI_REQUIRES(sizeof...(Ts) && !aux::is_array<TExpected, Ts...>::value) = 0> auto operator()(Ts&&... args) noexcept { return to_impl<TExpected>(aux::make_index_sequence<sizeof...(Ts)>{}, static_cast<Ts&&>(args)...); } protected: using scope_t::create; using scope_t::is_referable; using scope_t::try_create; template <class, class> static void try_create(...); private: template <class T, int... Ns, class... Ts> auto to_impl(aux::index_sequence<Ns...>, Ts&&... args) noexcept { using ctor_t = core::pool_t<ctor_arg_traits<T, Ns, Ts>...>; using dependency = dependency<TScope, TExpected, T, TName, TPriority, ctor_t>; return dependency{ctor_t{ctor_arg_traits<T, Ns, Ts>(static_cast<Ts&&>(args))...}}; } }; } namespace concepts { struct call_operator_with_one_argument {}; template <class> struct policy { template <class> struct requires_ : aux::false_type {}; }; struct arg_wrapper { using type = _; using expected = _; using given = _; using name = no_name; using arity = aux::integral_constant<int, 0>; using scope = scopes::deduce; using is_root = aux::false_type; template <class, class, class> struct resolve; }; aux::false_type callable_impl(...); template <class T, class TArg> auto callable_impl(const T&& t, TArg&& arg) -> aux::is_valid_expr<decltype(t(arg))>; template <class...> struct is_callable_impl; template <class T, class... Ts> struct is_callable_impl<T, Ts...> { using callable_with_arg = decltype(callable_impl(aux::declval<T>(), arg_wrapper{})); using type = aux::conditional_t<callable_with_arg::value, typename is_callable_impl<Ts...>::type, typename policy<T>::template requires_<call_operator_with_one_argument>>; }; template <> struct is_callable_impl<> : aux::true_type {}; template <class... Ts> struct is_callable : is_callable_impl<Ts...> {}; template <class... Ts> struct is_callable<core::pool<aux::type_list<Ts...>>> : is_callable_impl<Ts...> {}; template <> struct is_callable<void> { using type = policy<void>::requires_<call_operator_with_one_argument>; }; template <class... Ts> using callable = typename is_callable<Ts...>::type; } namespace providers { class stack_over_heap { public: template <class TInitialization, class T, class... TArgs> struct is_creatable { static constexpr auto value = concepts::creatable<TInitialization, T, TArgs...>::value; }; template <class T, class... TArgs> auto get(const type_traits::direct&, const type_traits::heap&, TArgs&&... args) const { return new T(static_cast<TArgs&&>(args)...); } template <class T, class... TArgs> auto get(const type_traits::uniform&, const type_traits::heap&, TArgs&&... args) const { return new T{static_cast<TArgs&&>(args)...}; } template <class T, class... TArgs> auto get(const type_traits::direct&, const type_traits::stack&, TArgs&&... args) const { return T(static_cast<TArgs&&>(args)...); } template <class T, class... TArgs> auto get(const type_traits::uniform&, const type_traits::stack&, TArgs&&... args) const { return T{static_cast<TArgs&&>(args)...}; } }; } namespace scopes { class singleton { template <class T, class = decltype(aux::has_shared_ptr__(aux::declval<T>()))> class scope_impl { public: template <class T_, class> using is_referable = typename wrappers::shared<singleton, T&>::template is_referable<T_>; template <class, class, class TProvider> static decltype(wrappers::shared<singleton, T&>{aux::declval<TProvider>().get(type_traits::stack{})}) try_create( const TProvider&); template <class, class, class TProvider> auto create(const TProvider& provider) { return create_impl(provider); } private: template <class TProvider> wrappers::shared<singleton, T&> create_impl(const TProvider& provider) { static auto object(provider.get(type_traits::stack{})); return wrappers::shared<singleton, T&>(object); } }; template <class T> class scope_impl<T, aux::true_type> { public: template <class T_, class> using is_referable = typename wrappers::shared<singleton, T>::template is_referable<T_>; template <class, class, class TProvider, class T_ = aux::decay_t<decltype(aux::declval<TProvider>().get())>> static decltype(wrappers::shared<singleton, T_>{std::shared_ptr<T_>{std::shared_ptr<T_>{aux::declval<TProvider>().get()}}}) try_create(const TProvider&); template <class, class, class TProvider> auto create(const TProvider& provider) { return create_impl<aux::decay_t<decltype(provider.get())>>(provider); } private: template <class T_, class TProvider> auto create_impl(const TProvider& provider) { static std::shared_ptr<T_> object{provider.get()}; return wrappers::shared<singleton, T_, std::shared_ptr<T_>&>{object}; } }; public: template <class, class T> using scope = scope_impl<T>; }; } static constexpr __BOOST_DI_UNUSED scopes::singleton singleton{}; namespace scopes { class unique { public: template <class, class> class scope { public: template <class...> using is_referable = aux::false_type; template <class T, class, class TProvider> static decltype(wrappers::unique<unique, decltype(aux::declval<TProvider>().get( typename TProvider::config::template memory_traits<T>::type{}))>{ aux::declval<TProvider>().get(typename TProvider::config::template memory_traits<T>::type{})}) try_create(const TProvider&); template <class T, class, class TProvider> auto create(const TProvider& provider) const { using memory = typename TProvider::config::template memory_traits<T>::type; using wrapper = wrappers::unique<unique, decltype(provider.get(memory{}))>; return wrapper{provider.get(memory{})}; } }; }; } static constexpr __BOOST_DI_UNUSED scopes::unique unique{}; namespace type_traits { template <class T> struct scope_traits { using type = scopes::unique; }; template <class T> struct scope_traits<T&> { using type = scopes::singleton; }; template <class T> struct scope_traits<std::shared_ptr<T>> { using type = scopes::singleton; }; template <class T> struct scope_traits<boost::shared_ptr<T>> { using type = scopes::singleton; }; template <class T> struct scope_traits<std::weak_ptr<T>> { using type = scopes::singleton; }; } #if !defined(BOOST_DI_CFG) #define BOOST_DI_CFG ::boost::di::v1_1_0::config #endif template <class... TPolicies, __BOOST_DI_REQUIRES_MSG(concepts::callable<TPolicies...>) = 0> inline auto make_policies(TPolicies... args) noexcept { return core::pool_t<TPolicies...>(static_cast<TPolicies&&>(args)...); } struct config { template <class T> auto provider(T*) noexcept { return providers::stack_over_heap{}; } template <class T> auto policies(T*) noexcept { return make_policies(); } template <class T> using scope_traits = type_traits::scope_traits<T>; template <class T> using memory_traits = type_traits::memory_traits<T>; }; namespace detail { template <class...> struct bind; template <class TScope> struct bind<int, TScope> { using type = core::dependency<TScope>; }; template <class TScope, class T> struct bind<int, TScope, T> { using type = core::dependency<TScope, T>; }; template <class TScope, class... Ts> struct bind<int, TScope, Ts...> { using type = core::dependency<TScope, concepts::any_of<Ts...>>; }; } template <class... Ts> #if defined(__cpp_variable_templates) typename #else struct bind : #endif detail::bind<__BOOST_DI_REQUIRES_MSG(concepts::boundable<concepts::any_of<Ts...>>), scopes::deduce, Ts...>::type #if defined(__cpp_variable_templates) bind #endif {}; static constexpr __BOOST_DI_UNUSED core::override override{}; namespace concepts { struct get {}; struct is_creatable {}; template <class> struct provider { template <class...> struct requires_ : aux::false_type {}; }; template <class T> typename provider<T>::template requires_<get, is_creatable> providable_impl(...); template <class T> auto providable_impl(T&& t) -> aux::is_valid_expr<decltype(t.template get<_>(type_traits::direct{}, type_traits::heap{})), decltype(t.template get<_>(type_traits::direct{}, type_traits::heap{}, int{})), decltype(t.template get<_>(type_traits::uniform{}, type_traits::stack{})), decltype(t.template get<_>(type_traits::uniform{}, type_traits::stack{}, int{})), decltype(T::template is_creatable<type_traits::direct, type_traits::heap, _>::value), decltype(T::template is_creatable<type_traits::uniform, type_traits::stack, _, int>::value)>; template <class T> struct providable__ { using type = decltype(providable_impl<T>(aux::declval<T>())); }; template <class T> using providable = typename providable__<T>::type; } namespace concepts { template <class> struct policies {}; struct providable_type {}; struct callable_type {}; template <class> struct config { template <class...> struct requires_ : aux::false_type {}; }; template <class TConfig> struct injector { using config = TConfig; using deps = aux::type_list<>; template <class T> T create() const; }; aux::false_type configurable_impl(...); template <class T> auto configurable_impl(T &&) -> aux::is_valid_expr<decltype(aux::declval<T>().provider((injector<T>*)0)), decltype(aux::declval<T>().policies((injector<T>*)0))>; template <class T1, class T2> struct get_configurable_error : aux::type_list<T1, T2> {}; template <class T> struct get_configurable_error<aux::true_type, T> { using type = T; }; template <class T> struct get_configurable_error<T, aux::true_type> { using type = T; }; template <> struct get_configurable_error<aux::true_type, aux::true_type> : aux::true_type {}; template <class T> auto is_configurable(const aux::true_type&) { return typename get_configurable_error<decltype(providable<decltype(aux::declval<T>().provider((injector<T>*)0))>()), decltype(callable<decltype(aux::declval<T>().policies((injector<T>*)0))>())>::type{}; } template <class T> auto is_configurable(const aux::false_type&) { return typename config<T>::template requires_<provider<providable_type(...)>, policies<callable_type(...)>>{}; } template <class T> struct configurable__ { using type = decltype(is_configurable<T>(decltype(configurable_impl(aux::declval<T>())){})); }; template <class T> using configurable = typename configurable__<T>::type; } namespace core { struct binder { template <class TDefault, class> static TDefault resolve_impl(...) noexcept { return {}; } template <class, class TConcept, class TDependency> static decltype(auto) resolve_impl(aux::pair<TConcept, TDependency>* dep) noexcept { return static_cast<TDependency&>(*dep); } template <class, class TConcept, class TScope, class TExpected, class TGiven, class TName, class TCtor, template <class, class, class, class, class, class> class TDependency> static decltype(auto) resolve_impl( aux::pair<TConcept, TDependency<TScope, TExpected, TGiven, TName, override, TCtor>>* dep) noexcept { return static_cast<TDependency<TScope, TExpected, TGiven, TName, override, TCtor>&>(*dep); } template <class TDefault, class> static TDefault resolve_impl__(...); template <class, class TConcept, class TDependency> static TDependency resolve_impl__(aux::pair<TConcept, TDependency>*); template <class, class TConcept, class TScope, class TExpected, class TGiven, class TName, class TCtor, template <class, class, class, class, class, class> class TDependency> static dependency<TScope, TExpected, TGiven, TName, override, TCtor> resolve_impl__( aux::pair<TConcept, TDependency<TScope, TExpected, TGiven, TName, override, TCtor>>*); template <class TDeps, class T, class TName, class TDefault> struct resolve__ { using type = decltype(resolve_impl__<TDefault, dependency_concept<aux::decay_t<T>, TName>>((TDeps*)0)); }; #if (defined(__CLANG__) && __CLANG__ >= 3'9) // template <class TDeps, class T> static T& resolve_(TDeps* deps, const aux::type<T&>&) noexcept { return static_cast<T&>(*deps); } template <class TDeps, class T> static T resolve_(TDeps*, const aux::type<T>&) noexcept { return {}; } #endif template <class, class T> struct resolve_template_impl { using type = T; }; template <class TDeps, template <class...> class T, class... Ts> struct resolve_template_impl<TDeps, aux::identity<T<Ts...>>> { using type = T<typename resolve_template_impl< TDeps, aux::remove_qualifiers_t<typename resolve__< TDeps, Ts, no_name, dependency<scopes::deduce, aux::decay_t<Ts>>>::type::given>>::type...>; }; template <class T, class TName = no_name, class TDefault = dependency<scopes::deduce, aux::decay_t<T>>, class TDeps> static decltype(auto) resolve(TDeps* deps) noexcept { using dependency = dependency_concept<aux::decay_t<T>, TName>; #if (defined(__CLANG__) && __CLANG__ >= 3'9) // return resolve_(deps, aux::type<decltype(resolve_impl<TDefault, dependency>((TDeps*)0))>{}); #else return resolve_impl<TDefault, dependency>(deps); #endif } template <class TDeps, class T, class TName = no_name, class TDefault = dependency<scopes::deduce, aux::decay_t<T>>> using resolve_t = typename resolve__<TDeps, T, TName, TDefault>::type; template <class TDeps, class T> using resolve_template_t = typename resolve_template_impl<TDeps, aux::remove_qualifiers_t<T>>::type; }; } namespace core { template <class T, class TInjector, class TError = aux::false_type> struct is_referable__ { static constexpr auto value = dependency__<binder::resolve_t<TInjector, T>>::template is_referable<T, typename TInjector::config>::value; }; template <class T, class TInjector> struct is_referable__<T, TInjector, aux::true_type> { static constexpr auto value = true; }; template <class T, class TInjector, class TError> struct is_creatable__ { static constexpr auto value = injector__<TInjector>::template is_creatable<T>::value; }; template <class T, class TInjector> struct is_creatable__<T, TInjector, aux::false_type> { static constexpr auto value = true; }; template <class, class> struct is_copy_ctor__ : aux::false_type {}; template <class T> struct is_copy_ctor__<T, T> : aux::true_type {}; template <class T> struct is_copy_ctor__<T, const T> : aux::true_type {}; template <class TParent, class TInjector, class TError = aux::false_type> struct any_type { template <class T, class = __BOOST_DI_REQUIRES(is_creatable__<T, TInjector, TError>::value)> operator T() { return static_cast<const core::injector__<TInjector>&>(injector_).create_impl(aux::type<T>{}); } const TInjector& injector_; }; template <class TParent, class TInjector, class TError = aux::false_type, class TRefError = aux::false_type> struct any_type_ref { template <class T, class = __BOOST_DI_REQUIRES(is_creatable__<T, TInjector, TError>::value)> operator T() { return static_cast<const core::injector__<TInjector>&>(injector_).create_impl(aux::type<T>{}); } template <class T, class = __BOOST_DI_REQUIRES(is_referable__<T&&, TInjector, TRefError>::value), class = __BOOST_DI_REQUIRES(is_creatable__<T&&, TInjector, TError>::value)> operator T &&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_impl(aux::type<T&&>{}); } template <class T, class = __BOOST_DI_REQUIRES(is_referable__<T&, TInjector, TRefError>::value), class = __BOOST_DI_REQUIRES(is_creatable__<T&, TInjector, TError>::value)> operator T&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_impl(aux::type<T&>{}); } template <class T, class = __BOOST_DI_REQUIRES(is_referable__<const T&, TInjector, TRefError>::value), class = __BOOST_DI_REQUIRES(is_creatable__<const T&, TInjector, TError>::value)> operator const T&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_impl(aux::type<const T&>{}); } const TInjector& injector_; }; template <class TParent, class TInjector, class TError = aux::false_type> struct any_type_1st { template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value), class = __BOOST_DI_REQUIRES(is_creatable__<T, TInjector, TError>::value)> operator T() { return static_cast<const core::injector__<TInjector>&>(injector_).create_impl(aux::type<T>{}); } const TInjector& injector_; }; template <class TParent, class TInjector, class TError = aux::false_type, class TRefError = aux::false_type> struct any_type_1st_ref { template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value), class = __BOOST_DI_REQUIRES(is_creatable__<T, TInjector, TError>::value)> operator T() { return static_cast<const core::injector__<TInjector>&>(injector_).create_impl(aux::type<T>{}); } template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value), class = __BOOST_DI_REQUIRES(is_referable__<T&&, TInjector, TRefError>::value), class = __BOOST_DI_REQUIRES(is_creatable__<T&&, TInjector, TError>::value)> operator T &&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_impl(aux::type<T&&>{}); } template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value), class = __BOOST_DI_REQUIRES(is_referable__<T&, TInjector, TRefError>::value), class = __BOOST_DI_REQUIRES(is_creatable__<T&, TInjector, TError>::value)> operator T&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_impl(aux::type<T&>{}); } template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value), class = __BOOST_DI_REQUIRES(is_referable__<const T&, TInjector, TRefError>::value), class = __BOOST_DI_REQUIRES(is_creatable__<const T&, TInjector, TError>::value)> operator const T&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_impl(aux::type<const T&>{}); } const TInjector& injector_; }; namespace successful { template <class TParent, class TInjector> struct any_type { template <class T> operator T() { return static_cast<const core::injector__<TInjector>&>(injector_).create_successful_impl(aux::type<T>{}); } const TInjector& injector_; }; template <class TParent, class TInjector> struct any_type_ref { template <class T> operator T() { return static_cast<const core::injector__<TInjector>&>(injector_).create_successful_impl(aux::type<T>{}); } template <class T, class = __BOOST_DI_REQUIRES(is_referable__<T&&, TInjector>::value)> operator T &&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_successful_impl(aux::type<T&&>{}); } template <class T, class = __BOOST_DI_REQUIRES(is_referable__<T&, TInjector>::value)> operator T&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_successful_impl(aux::type<T&>{}); } template <class T, class = __BOOST_DI_REQUIRES(is_referable__<const T&, TInjector>::value)> operator const T&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_successful_impl(aux::type<const T&>{}); } const TInjector& injector_; }; template <class TParent, class TInjector> struct any_type_1st { template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value)> operator T() { return static_cast<const core::injector__<TInjector>&>(injector_).create_successful_impl(aux::type<T>{}); } const TInjector& injector_; }; template <class TParent, class TInjector> struct any_type_1st_ref { template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value)> operator T() { return static_cast<const core::injector__<TInjector>&>(injector_).create_successful_impl(aux::type<T>{}); } template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value), class = __BOOST_DI_REQUIRES(is_referable__<T&&, TInjector>::value)> operator T &&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_successful_impl(aux::type<T&&>{}); } template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value), class = __BOOST_DI_REQUIRES(is_referable__<T&, TInjector>::value)> operator T&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_successful_impl(aux::type<T&>{}); } template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value), class = __BOOST_DI_REQUIRES(is_referable__<const T&, TInjector>::value)> operator const T&() const { return static_cast<const core::injector__<TInjector>&>(injector_).create_successful_impl(aux::type<const T&>{}); } const TInjector& injector_; }; } template <class> struct any_type_fwd { template <class T> operator T(); private: template <class T> operator const T&() const; }; template <class> struct any_type_ref_fwd { template <class T> operator T(); template <class T> operator T&() const; template <class T> operator T &&() const; template <class T> operator const T&() const; }; template <class TParent> struct any_type_1st_fwd { template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value)> operator T(); private: template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value)> operator const T&() const; }; template <class TParent> struct any_type_1st_ref_fwd { template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value)> operator T(); template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value)> operator T&() const; template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value)> operator T &&() const; template <class T, class = __BOOST_DI_REQUIRES(!is_copy_ctor__<TParent, T>::value)> operator const T&() const; }; } namespace core { template <class...> struct arg_wrapper; template <class T, class TName, class TIsRoot, template <class...> class TList, class... TCtor, class TDependency, class TDeps> struct arg_wrapper<T, TName, TIsRoot, TList<TCtor...>, TDependency, TDeps> { using type __BOOST_DI_UNUSED = T; using expected __BOOST_DI_UNUSED = typename TDependency::expected; using given __BOOST_DI_UNUSED = typename TDependency::given; using name __BOOST_DI_UNUSED = TName; using arity __BOOST_DI_UNUSED = aux::integral_constant<int, sizeof...(TCtor)>; using scope __BOOST_DI_UNUSED = typename TDependency::scope; using is_root __BOOST_DI_UNUSED = TIsRoot; template <class T_, class TName_, class TDefault_> using resolve = decltype(core::binder::resolve<T_, TName_, TDefault_>((TDeps*)0)); }; template <class T> struct allow_void : T {}; template <> struct allow_void<void> : aux::true_type {}; class policy { template <class TArg, class TPolicy, class TPolicies, __BOOST_DI_REQUIRES(!aux::is_base_of<_, aux::remove_reference_t<typename TArg::type>>::value) = 0> static void call_impl(const TPolicies& policies) noexcept { static_cast<const TPolicy&>(policies)(TArg{}); } template <class TArg, class, class TPolicies, __BOOST_DI_REQUIRES(aux::is_base_of<_, aux::remove_reference_t<typename TArg::type>>::value) = 0> static void call_impl(const TPolicies&) noexcept {} template <class TArg, class TPolicy> struct try_call_impl : aux::conditional_t<aux::is_base_of<_, aux::remove_reference_t<typename TArg::type>>::value, aux::true_type, allow_void<decltype((aux::declval<TPolicy>())(aux::declval<TArg>()))>> {}; public: template <class, class> struct try_call; template <class TArg, class... TPolicies> struct try_call<TArg, pool_t<TPolicies...>> : aux::is_same<aux::bool_list<aux::always<TPolicies>::value...>, aux::bool_list<try_call_impl<TArg, TPolicies>::value...>> {}; template <class TArg, class... TPolicies> static void call(__BOOST_DI_UNUSED const pool_t<TPolicies...>& policies) noexcept { (void)aux::swallow{0, (call_impl<TArg, TPolicies>(policies), 0)...}; } }; } namespace core { #if (BOOST_DI_CFG_DIAGNOSTICS_LEVEL >= 2) template <class T> struct creating { creating() { type(); } static inline T type(_ = "creating..."); }; #endif template <class, class, class> struct try_provider; template <class T, class TInjector, class TProvider, class TInitialization, template <class...> class TList, class... TCtor> struct try_provider<aux::pair<T, aux::pair<TInitialization, TList<TCtor...>>>, TInjector, TProvider> { using injector = TInjector; using config = typename TInjector::config; template <class> struct is_creatable { static constexpr auto value = TProvider::template is_creatable<TInitialization, T, typename injector__<TInjector>::template try_create<TCtor>::type...>::value; }; template <class TMemory = type_traits::heap> auto get(const TMemory& = {}) const -> aux::enable_if_t<is_creatable<TMemory>::value, aux::conditional_t<aux::is_same<TMemory, type_traits::stack>::value, T, aux::remove_reference_t<T>*>>; }; template <class, class, class> struct provider; template <class T, class TName, class TInjector, class TInitialization, template <class...> class TList, class... TCtor> struct provider<aux::pair<T, aux::pair<TInitialization, TList<TCtor...>>>, TName, TInjector> { using injector = TInjector; using config = typename TInjector::config; template <class, class... TArgs> struct is_creatable { using type = decltype(aux::declval<injector__<TInjector>>().cfg().provider((TInjector*)0)); static constexpr auto value = type::template is_creatable<TInitialization, T, TArgs...>::value; }; template <class TMemory = type_traits::heap> auto get(const TMemory& memory = {}) const { return get_impl(memory, ((const injector__<TInjector>*)injector_)->create_impl(aux::type<TCtor>{})...); } template <class TMemory, class... TArgs, __BOOST_DI_REQUIRES(is_creatable<TMemory, TArgs...>::value) = 0> auto get_impl(const TMemory& memory, TArgs&&... args) const { #if (BOOST_DI_CFG_DIAGNOSTICS_LEVEL >= 2) (void)aux::conditional_t<injector__<TInjector>::template is_creatable<T>::value, _, creating<T>>{}; #endif return cfg().provider(injector_).template get<T>(TInitialization{}, memory, static_cast<TArgs&&>(args)...); } template <class TMemory, class... TArgs, __BOOST_DI_REQUIRES(!is_creatable<TMemory, TArgs...>::value) = 0> auto get_impl(const TMemory&, TArgs&&...) const { #if (BOOST_DI_CFG_DIAGNOSTICS_LEVEL > 0) return concepts::creatable_error<TInitialization, TName, T*, TArgs...>(); #else return nullptr; #endif } auto& super() const { return *injector_; } auto& cfg() const { return ((injector__<TInjector>*)injector_)->cfg(); } const TInjector* injector_; }; namespace successful { template <class, class> struct provider; template <class T, class TInjector, class TInitialization, template <class...> class TList, class... TCtor> struct provider<aux::pair<T, aux::pair<TInitialization, TList<TCtor...>>>, TInjector> { using injector = TInjector; using config = typename TInjector::config; template <class TMemory = type_traits::heap> auto get(const TMemory& memory = {}) const { return cfg().provider(injector_).template get<T>( TInitialization{}, memory, ((const injector__<TInjector>*)injector_)->create_successful_impl(aux::type<TCtor>{})...); } auto& super() const { return *injector_; } auto& cfg() const { return ((injector__<TInjector>*)injector_)->cfg(); } const TInjector* injector_; }; } } namespace core { namespace successful { template <class T, class TWrapper> struct wrapper { inline operator T() noexcept { return wrapper_; } TWrapper wrapper_; }; } template <class T, class TWrapper, class = int> struct wrapper_impl { inline operator T() noexcept { return wrapper_; } TWrapper wrapper_; }; template <class T, template <class...> class TWrapper, class TScope, class T_, class... Ts> struct wrapper_impl<T, TWrapper<TScope, T_, Ts...>, __BOOST_DI_REQUIRES(!aux::is_convertible<TWrapper<TScope, T_, Ts...>, T>::value)> { inline operator T() noexcept { return typename concepts::scoped<TScope, aux::remove_qualifiers_t<T_>>::template is_not_convertible_to<T>{}; } TWrapper<TScope, T_, Ts...> wrapper_; }; template <class T, class TWrapper> using wrapper = wrapper_impl<T, TWrapper>; } namespace core { struct from_injector {}; struct from_deps {}; struct init {}; struct with_error {}; template <class T, class, class> struct referable { using type = T; }; template <class T, class TConfig, class TDependency> struct referable<T&, TConfig, TDependency> { using type = aux::conditional_t<TDependency::template is_referable<T&, TConfig>::value, T&, T>; }; template <class T, class TConfig, class TDependency> struct referable<const T&, TConfig, TDependency> { using type = aux::conditional_t<TDependency::template is_referable<const T&, TConfig>::value, const T&, T>; }; #if defined(__MSVC__) template <class T, class TConfig, class TDependency> struct referable<T&&, TConfig, TDependency> { using type = aux::conditional_t<TDependency::template is_referable<T&&, TConfig>::value, T&&, T>; }; #endif template <class T, class TConfig, class TDependency> using referable_t = typename referable<T, TConfig, TDependency>::type; #if defined(__MSVC__) template <class T, class TInjector> inline auto build(TInjector&& injector) noexcept { return T{static_cast<TInjector&&>(injector)}; } #endif template <class TConfig, class TPolicies = pool<>, class... TDeps> class injector : public injector_base, public pool<bindings_t<TDeps...>> { using pool_t = pool<bindings_t<TDeps...>>; protected: template <class T, class TName = no_name, class TIsRoot = aux::false_type> struct is_creatable { using dependency_t = binder::resolve_t<injector, T, TName>; using ctor_t = typename type_traits::ctor_traits__<binder::resolve_template_t<injector, typename dependency_t::given>, T, typename dependency_t::ctor>::type; using ctor_args_t = typename ctor_t::second::second; static constexpr auto value = aux::is_convertible<decltype(dependency__<dependency_t>::template try_create<T, TName>( try_provider<ctor_t, injector, decltype(aux::declval<TConfig>().provider((injector*)0))>{})), T>::value && policy::template try_call<arg_wrapper<T, TName, TIsRoot, ctor_args_t, dependency_t, pool_t>, TPolicies>::value; }; auto& cfg() { return config_; } const auto& cfg() const { return config_; } public: using deps = bindings_t<TDeps...>; using config = TConfig; injector(injector&&) = default; template <class... TArgs> explicit injector(const init&, TArgs... args) noexcept : injector{from_deps{}, static_cast<TArgs&&>(args)...} {} template <class TConfig_, class TPolicies_, class... TDeps_> explicit injector(injector<TConfig_, TPolicies_, TDeps_...>&& other) noexcept : injector{from_injector{}, static_cast<injector<TConfig_, TPolicies_, TDeps_...>&&>(other), deps{}} {} template <class T> injector& operator=(T&& other) noexcept { static_cast<pool_t&>(*this).operator=(static_cast<T&&>(other)); return *this; } template <class T, __BOOST_DI_REQUIRES(is_creatable<T, no_name, aux::true_type>::value) = 0> T create() const { return __BOOST_DI_TYPE_WKND(T) create_successful_impl<aux::true_type>(aux::type<T>{}); } template <class T, __BOOST_DI_REQUIRES(!is_creatable<T, no_name, aux::true_type>::value) = 0> __BOOST_DI_DEPRECATED("creatable constraint not satisfied") T // clang-format off create // clang-format on () const { return __BOOST_DI_TYPE_WKND(T) create_impl<aux::true_type>(aux::type<T>{}); } template <template <class...> class T, __BOOST_DI_REQUIRES( is_creatable<binder::resolve_template_t<injector, aux::identity<T<>>>, no_name, aux::true_type>::value) = 0> binder::resolve_template_t<injector, aux::identity<T<>>> // clang-format off create() // clang-format on const { using type = binder::resolve_template_t<injector, aux::identity<T<>>>; return __BOOST_DI_TYPE_WKND(type) create_successful_impl<aux::true_type>(aux::type<type>{}); } template <template <class...> class T, __BOOST_DI_REQUIRES( !is_creatable<binder::resolve_template_t<injector, aux::identity<T<>>>, no_name, aux::true_type>::value) = 0> // __BOOST_DI_DEPRECATED("creatable constraint not satisfied") binder::resolve_template_t<injector, aux::identity<T<>>> // clang-format off create() // clang-format on const { using type = binder::resolve_template_t<injector, aux::identity<T<>>>; return __BOOST_DI_TYPE_WKND(type) create_impl<aux::true_type>(aux::type<type>{}); } protected: template <class T> struct try_create { using type = aux::conditional_t<is_creatable<T>::value, T, void>; }; template <class TParent> struct try_create<any_type_fwd<TParent>> { using type = any_type<TParent, injector, with_error>; }; template <class TParent> struct try_create<any_type_ref_fwd<TParent>> { using type = any_type_ref<TParent, injector, with_error>; }; template <class TParent> struct try_create<any_type_1st_fwd<TParent>> { using type = any_type_1st<TParent, injector, with_error>; }; template <class TParent> struct try_create<any_type_1st_ref_fwd<TParent>> { using type = any_type_1st_ref<TParent, injector, with_error>; }; template <class TName, class T> struct try_create<::boost::di::v1_1_0::named<TName, T>> { using type = aux::conditional_t<is_creatable<T, TName>::value, T, void>; }; template <class TParent, int N, class T> struct try_create<core::ctor_arg<TParent, N, T&&>> { using type = aux::conditional_t<is_creatable<T>::value, T, void>; }; template <class TParent, int N> struct try_create<core::ctor_arg<TParent, N, const placeholders::arg&>> { using type = any_type_1st_ref<TParent, injector, with_error>; }; template <class T> struct try_create<self<T>> { using type = injector; }; template <class TIsRoot = aux::false_type, class T> auto create_impl(const aux::type<T>&) const { return create_impl__<TIsRoot, T>(); } template <class TIsRoot = aux::false_type, class TParent> auto create_impl(const aux::type<any_type_fwd<TParent>>&) const { return any_type<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_impl(const aux::type<any_type_ref_fwd<TParent>>&) const { return any_type_ref<TParent, injector, aux::false_type, aux::true_type>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_impl(const aux::type<any_type_1st_fwd<TParent>>&) const { return any_type_1st<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_impl(const aux::type<any_type_1st_ref_fwd<TParent>>&) const { return any_type_1st_ref<TParent, injector, aux::false_type, aux::true_type>{*this}; } template <class TIsRoot = aux::false_type, class T, class TName> auto create_impl(const aux::type<::boost::di::v1_1_0::named<TName, T>>&) const { return create_impl__<TIsRoot, T, TName>(); } template <class TIsRoot = aux::false_type, class TParent, int N, class T> auto create_impl(const aux::type<core::ctor_arg<TParent, N, T>>&) const { auto& dependency = binder::resolve<TParent>((injector*)this); return static_cast<core::ctor_arg<TParent, N, T>&>(dependency); } template <class TIsRoot = aux::false_type, class TParent, int N> auto create_impl(const aux::type<core::ctor_arg<TParent, N, const placeholders::arg&>>&) const { return any_type_1st_ref<TParent, injector, aux::false_type, aux::true_type>{*this}; } template <class TIsRoot = aux::false_type, class T> auto create_successful_impl(const aux::type<T>&) const { return create_successful_impl__<TIsRoot, T>(); } template <class TIsRoot = aux::false_type, class TParent> auto create_successful_impl(const aux::type<any_type_fwd<TParent>>&) const { return successful::any_type<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_successful_impl(const aux::type<any_type_ref_fwd<TParent>>&) const { return successful::any_type_ref<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_successful_impl(const aux::type<any_type_1st_fwd<TParent>>&) const { return successful::any_type_1st<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_successful_impl(const aux::type<any_type_1st_ref_fwd<TParent>>&) const { return successful::any_type_1st_ref<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class T, class TName> auto create_successful_impl(const aux::type<::boost::di::v1_1_0::named<TName, T>>&) const { return create_successful_impl__<TIsRoot, T, TName>(); } template <class TIsRoot = aux::false_type, class TParent, int N, class T> auto create_successful_impl(const aux::type<core::ctor_arg<TParent, N, T>>&) const { auto& dependency = binder::resolve<TParent>((injector*)this); return static_cast<core::ctor_arg<TParent, N, T>&>(dependency); } template <class TIsRoot = aux::false_type, class TParent, int N> auto create_successful_impl(const aux::type<core::ctor_arg<TParent, N, const placeholders::arg&>>&) const { return any_type_1st_ref<TParent, injector, aux::false_type, aux::true_type>{*this}; } template <class TIsRoot = aux::false_type, class T> decltype(auto) create_successful_impl(const aux::type<self<T>>&) const { return *this; } private: explicit injector(const from_deps&) noexcept {} template <class... TArgs> explicit injector(const from_deps&, TArgs... args) noexcept : pool_t{bindings_t<TArgs...>{}, core::pool_t<TArgs...>{static_cast<TArgs&&>(args)...}} {} template <class TInjector, class... TArgs> injector(const from_injector&, TInjector&& injector, const aux::type_list<TArgs...>&) noexcept #if defined(__MSVC__) : pool_t { bindings_t<TArgs...>{}, pool_t { build<TArgs>(static_cast<TInjector&&>(injector))... } } #else : pool_t { bindings_t<TArgs...>{}, pool_t { TArgs{static_cast<TInjector&&>(injector)}... } } #endif {} template <class TInjector> injector(const from_injector&, TInjector&&, const aux::type_list<>&) noexcept {} template <class TIsRoot = aux::false_type, class T, class TName = no_name> auto create_impl__() const { auto&& dependency = binder::resolve<T, TName>((injector*)this); using dependency_t = typename aux::remove_reference<decltype(dependency)>::type; using ctor_t = typename type_traits::ctor_traits__<binder::resolve_template_t<injector, typename dependency_t::given>, T, typename dependency_t::ctor>::type; using provider_t = core::provider<ctor_t, TName, injector>; auto& creatable_dept = static_cast<dependency__<dependency_t>&>(dependency); using wrapper_t = decltype(creatable_dept.template create<T, TName>(provider_t{this})); using ctor_args_t = typename ctor_t::second::second; policy::template call<arg_wrapper<T, TName, TIsRoot, ctor_args_t, dependency_t, pool_t>>( ((injector*)this)->cfg().policies(this)); return wrapper<T, wrapper_t>{creatable_dept.template create<T, TName>(provider_t{this})}; } template <class TIsRoot = aux::false_type, class T, class TName = no_name> auto create_successful_impl__() const { auto&& dependency = binder::resolve<T, TName>((injector*)this); using dependency_t = typename aux::remove_reference<decltype(dependency)>::type; using ctor_t = typename type_traits::ctor_traits__<binder::resolve_template_t<injector, typename dependency_t::given>, T, typename dependency_t::ctor>::type; using provider_t = successful::provider<ctor_t, injector>; auto& creatable_dept = static_cast<dependency__<dependency_t>&>(dependency); using wrapper_t = decltype(creatable_dept.template create<T, TName>(provider_t{this})); using create_t = referable_t<T, config, dependency__<dependency_t>>; using ctor_args_t = typename ctor_t::second::second; policy::template call<arg_wrapper<T, TName, TIsRoot, ctor_args_t, dependency_t, pool_t>>( ((injector*)this)->cfg().policies(this)); return successful::wrapper<create_t, wrapper_t>{creatable_dept.template create<T, TName>(provider_t{this})}; } config config_; }; template <class TConfig, class... TDeps> class injector<TConfig, pool<>, TDeps...> : public injector_base, public pool<bindings_t<TDeps...>> { using pool_t = pool<bindings_t<TDeps...>>; protected: template <class T, class TName = no_name, class TIsRoot = aux::false_type> struct is_creatable { using dependency_t = binder::resolve_t<injector, T, TName>; using ctor_t = typename type_traits::ctor_traits__<binder::resolve_template_t<injector, typename dependency_t::given>, T, typename dependency_t::ctor>::type; using ctor_args_t = typename ctor_t::second::second; static constexpr auto value = aux::is_convertible<decltype(dependency__<dependency_t>::template try_create<T, TName>( try_provider<ctor_t, injector, decltype(aux::declval<TConfig>().provider((injector*)0))>{})), T>::value; }; auto& cfg() { return config_; } const auto& cfg() const { return config_; } public: using deps = bindings_t<TDeps...>; using config = TConfig; injector(injector&&) = default; template <class... TArgs> explicit injector(const init&, TArgs... args) noexcept : injector{from_deps{}, static_cast<TArgs&&>(args)...} {} template <class TConfig_, class TPolicies_, class... TDeps_> explicit injector(injector<TConfig_, TPolicies_, TDeps_...>&& other) noexcept : injector{from_injector{}, static_cast<injector<TConfig_, TPolicies_, TDeps_...>&&>(other), deps{}} {} template <class T> injector& operator=(T&& other) noexcept { static_cast<pool_t&>(*this).operator=(static_cast<T&&>(other)); return *this; } template <class T, __BOOST_DI_REQUIRES(is_creatable<T, no_name, aux::true_type>::value) = 0> T create() const { return __BOOST_DI_TYPE_WKND(T) create_successful_impl<aux::true_type>(aux::type<T>{}); } template <class T, __BOOST_DI_REQUIRES(!is_creatable<T, no_name, aux::true_type>::value) = 0> __BOOST_DI_DEPRECATED("creatable constraint not satisfied") T // clang-format off create // clang-format on () const { return __BOOST_DI_TYPE_WKND(T) create_impl<aux::true_type>(aux::type<T>{}); } template <template <class...> class T, __BOOST_DI_REQUIRES( is_creatable<binder::resolve_template_t<injector, aux::identity<T<>>>, no_name, aux::true_type>::value) = 0> binder::resolve_template_t<injector, aux::identity<T<>>> // clang-format off create() // clang-format on const { using type = binder::resolve_template_t<injector, aux::identity<T<>>>; return __BOOST_DI_TYPE_WKND(type) create_successful_impl<aux::true_type>(aux::type<type>{}); } template <template <class...> class T, __BOOST_DI_REQUIRES( !is_creatable<binder::resolve_template_t<injector, aux::identity<T<>>>, no_name, aux::true_type>::value) = 0> // __BOOST_DI_DEPRECATED("creatable constraint not satisfied") binder::resolve_template_t<injector, aux::identity<T<>>> // clang-format off create() // clang-format on const { using type = binder::resolve_template_t<injector, aux::identity<T<>>>; return __BOOST_DI_TYPE_WKND(type) create_impl<aux::true_type>(aux::type<type>{}); } protected: template <class T> struct try_create { using type = aux::conditional_t<is_creatable<T>::value, T, void>; }; template <class TParent> struct try_create<any_type_fwd<TParent>> { using type = any_type<TParent, injector, with_error>; }; template <class TParent> struct try_create<any_type_ref_fwd<TParent>> { using type = any_type_ref<TParent, injector, with_error>; }; template <class TParent> struct try_create<any_type_1st_fwd<TParent>> { using type = any_type_1st<TParent, injector, with_error>; }; template <class TParent> struct try_create<any_type_1st_ref_fwd<TParent>> { using type = any_type_1st_ref<TParent, injector, with_error>; }; template <class TName, class T> struct try_create<::boost::di::v1_1_0::named<TName, T>> { using type = aux::conditional_t<is_creatable<T, TName>::value, T, void>; }; template <class TParent, int N, class T> struct try_create<core::ctor_arg<TParent, N, T&&>> { using type = aux::conditional_t<is_creatable<T>::value, T, void>; }; template <class TParent, int N> struct try_create<core::ctor_arg<TParent, N, const placeholders::arg&>> { using type = any_type_1st_ref<TParent, injector, with_error>; }; template <class T> struct try_create<self<T>> { using type = injector; }; template <class TIsRoot = aux::false_type, class T> auto create_impl(const aux::type<T>&) const { return create_impl__<TIsRoot, T>(); } template <class TIsRoot = aux::false_type, class TParent> auto create_impl(const aux::type<any_type_fwd<TParent>>&) const { return any_type<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_impl(const aux::type<any_type_ref_fwd<TParent>>&) const { return any_type_ref<TParent, injector, aux::false_type, aux::true_type>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_impl(const aux::type<any_type_1st_fwd<TParent>>&) const { return any_type_1st<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_impl(const aux::type<any_type_1st_ref_fwd<TParent>>&) const { return any_type_1st_ref<TParent, injector, aux::false_type, aux::true_type>{*this}; } template <class TIsRoot = aux::false_type, class T, class TName> auto create_impl(const aux::type<::boost::di::v1_1_0::named<TName, T>>&) const { return create_impl__<TIsRoot, T, TName>(); } template <class TIsRoot = aux::false_type, class TParent, int N, class T> auto create_impl(const aux::type<core::ctor_arg<TParent, N, T>>&) const { auto& dependency = binder::resolve<TParent>((injector*)this); return static_cast<core::ctor_arg<TParent, N, T>&>(dependency); } template <class TIsRoot = aux::false_type, class TParent, int N> auto create_impl(const aux::type<core::ctor_arg<TParent, N, const placeholders::arg&>>&) const { return any_type_1st_ref<TParent, injector, aux::false_type, aux::true_type>{*this}; } template <class TIsRoot = aux::false_type, class T> auto create_successful_impl(const aux::type<T>&) const { return create_successful_impl__<TIsRoot, T>(); } template <class TIsRoot = aux::false_type, class TParent> auto create_successful_impl(const aux::type<any_type_fwd<TParent>>&) const { return successful::any_type<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_successful_impl(const aux::type<any_type_ref_fwd<TParent>>&) const { return successful::any_type_ref<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_successful_impl(const aux::type<any_type_1st_fwd<TParent>>&) const { return successful::any_type_1st<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class TParent> auto create_successful_impl(const aux::type<any_type_1st_ref_fwd<TParent>>&) const { return successful::any_type_1st_ref<TParent, injector>{*this}; } template <class TIsRoot = aux::false_type, class T, class TName> auto create_successful_impl(const aux::type<::boost::di::v1_1_0::named<TName, T>>&) const { return create_successful_impl__<TIsRoot, T, TName>(); } template <class TIsRoot = aux::false_type, class TParent, int N, class T> auto create_successful_impl(const aux::type<core::ctor_arg<TParent, N, T>>&) const { auto& dependency = binder::resolve<TParent>((injector*)this); return static_cast<core::ctor_arg<TParent, N, T>&>(dependency); } template <class TIsRoot = aux::false_type, class TParent, int N> auto create_successful_impl(const aux::type<core::ctor_arg<TParent, N, const placeholders::arg&>>&) const { return any_type_1st_ref<TParent, injector, aux::false_type, aux::true_type>{*this}; } template <class TIsRoot = aux::false_type, class T> decltype(auto) create_successful_impl(const aux::type<self<T>>&) const { return *this; } private: explicit injector(const from_deps&) noexcept {} template <class... TArgs> explicit injector(const from_deps&, TArgs... args) noexcept : pool_t{bindings_t<TArgs...>{}, core::pool_t<TArgs...>{static_cast<TArgs&&>(args)...}} {} template <class TInjector, class... TArgs> injector(const from_injector&, TInjector&& injector, const aux::type_list<TArgs...>&) noexcept #if defined(__MSVC__) : pool_t { bindings_t<TArgs...>{}, pool_t { build<TArgs>(static_cast<TInjector&&>(injector))... } } #else : pool_t { bindings_t<TArgs...>{}, pool_t { TArgs{static_cast<TInjector&&>(injector)}... } } #endif {} template <class TInjector> injector(const from_injector&, TInjector&&, const aux::type_list<>&) noexcept {} template <class TIsRoot = aux::false_type, class T, class TName = no_name> auto create_impl__() const { auto&& dependency = binder::resolve<T, TName>((injector*)this); using dependency_t = typename aux::remove_reference<decltype(dependency)>::type; using ctor_t = typename type_traits::ctor_traits__<binder::resolve_template_t<injector, typename dependency_t::given>, T, typename dependency_t::ctor>::type; using provider_t = core::provider<ctor_t, TName, injector>; auto& creatable_dept = static_cast<dependency__<dependency_t>&>(dependency); using wrapper_t = decltype(creatable_dept.template create<T, TName>(provider_t{this})); return wrapper<T, wrapper_t>{creatable_dept.template create<T, TName>(provider_t{this})}; } template <class TIsRoot = aux::false_type, class T, class TName = no_name> auto create_successful_impl__() const { auto&& dependency = binder::resolve<T, TName>((injector*)this); using dependency_t = typename aux::remove_reference<decltype(dependency)>::type; using ctor_t = typename type_traits::ctor_traits__<binder::resolve_template_t<injector, typename dependency_t::given>, T, typename dependency_t::ctor>::type; using provider_t = successful::provider<ctor_t, injector>; auto& creatable_dept = static_cast<dependency__<dependency_t>&>(dependency); using wrapper_t = decltype(creatable_dept.template create<T, TName>(provider_t{this})); using create_t = referable_t<T, config, dependency__<dependency_t>>; return successful::wrapper<create_t, wrapper_t>{creatable_dept.template create<T, TName>(provider_t{this})}; } config config_; }; } template <class T, class TInjector> auto create(const TInjector& injector) -> decltype(injector.template create<T>()) { return injector.template create<T>(); } template <template <class...> class T, class TInjector> auto create(const TInjector& injector) -> decltype(injector.template create<T>()) { return injector.template create<T>(); } template <class T, class TInjector> constexpr auto is_creatable(const TInjector&) { return core::injector__<TInjector>::template is_creatable<T, no_name, aux::true_type>::value; } template <template <class...> class T, class TInjector> constexpr auto is_creatable(const TInjector&) { return core::injector__<TInjector>::template is_creatable<core::binder::resolve_template_t<TInjector, aux::identity<T<>>>, no_name, aux::true_type>::value; } namespace detail { template <class> void create(const aux::true_type&) {} // clang-format off template <class> __BOOST_DI_DEPRECATED("creatable constraint not satisfied") void create (const aux::false_type&) {} // clang-format on template <class, class, class...> struct injector; template <class, class> struct is_creatable_impl; template <class TInjector, class TName, class T> struct is_creatable_impl<TInjector, named<TName, T>> { static constexpr auto value = core::injector__<TInjector>::template is_creatable<T, TName>::value; }; template <class TConfig, class T, class... TGivens> struct injector<TConfig, int, core::dependency<scopes::instance, T, aux::type_list<TGivens...>>> : core::injector<TConfig, core::pool<>, core::dependency<scopes::instance, T, aux::type_list<TGivens...>>> { template <class... Ts> injector(core::injector<Ts...>&& injector) noexcept : core::injector<TConfig, core::pool<>, core::dependency<scopes::instance, T, aux::type_list<TGivens...>>>( static_cast<core::injector<Ts...>&&>(injector)) { using injector_t = core::injector<Ts...>; int _[]{0, // clang-format off (detail:: create<T> ( aux::integral_constant<bool, is_creatable_impl<injector_t, TGivens>::value>{}), 0)...}; // clang-format on (void)_; } }; } #if defined(__MSVC__) template <class T, class... Ts> struct injector : detail::injector< BOOST_DI_CFG, __BOOST_DI_REQUIRES_MSG(concepts::boundable<aux::type<T, Ts...>>), core::dependency<scopes::instance, aux::unique_t<type_traits::named_decay_t<T>, type_traits::named_decay_t<Ts>...>, aux::type_list<type_traits::add_named_t<T>, type_traits::add_named_t<Ts>...>>> { using detail::injector< BOOST_DI_CFG, __BOOST_DI_REQUIRES_MSG(concepts::boundable<aux::type<T, Ts...>>), core::dependency<scopes::instance, aux::unique_t<type_traits::named_decay_t<T>, type_traits::named_decay_t<Ts>...>, aux::type_list<type_traits::add_named_t<T>, type_traits::add_named_t<Ts>...>>>::injector; }; #else template <class T, class... Ts> using injector = detail::injector< BOOST_DI_CFG, __BOOST_DI_REQUIRES_MSG(concepts::boundable<aux::type<T, Ts...>>), core::dependency<scopes::instance, aux::unique_t<type_traits::named_decay_t<T>, type_traits::named_decay_t<Ts>...>, aux::type_list<type_traits::add_named_t<T>, type_traits::add_named_t<Ts>...>>>; #endif // clang-format off #define __BOOST_DI_EXPOSE_IMPL__(...) decltype(::boost::di::v1_1_0::detail::__VA_ARGS__), #define __BOOST_DI_EXPOSE_IMPL(...) ::boost::di::v1_1_0::named<__BOOST_DI_EXPOSE_IMPL__ __VA_ARGS__> #define BOOST_DI_EXPOSE(...) __BOOST_DI_IF(__BOOST_DI_IBP(__VA_ARGS__), __BOOST_DI_EXPOSE_IMPL, __BOOST_DI_EXPAND)(__VA_ARGS__) // clang-format on #if defined(__MSVC__) #define __BOOST_DI_MAKE_INJECTOR(...) __VA_ARGS__ #else namespace detail { static auto make_injector = [](auto injector) { using injector_t = decltype(injector); struct i : injector_t { explicit i(injector_t&& other) : injector_t(static_cast<injector_t&&>(other)) {} }; return i{static_cast<injector_t&&>(injector)}; }; } #define __BOOST_DI_MAKE_INJECTOR(...) detail::make_injector(__VA_ARGS__) #endif template <class TConfig = BOOST_DI_CFG, class... TDeps, __BOOST_DI_REQUIRES_MSG(concepts::boundable<aux::type_list<TDeps...>>) = 0, __BOOST_DI_REQUIRES_MSG(concepts::configurable<TConfig>) = 0> inline auto make_injector(TDeps... args) noexcept { return __BOOST_DI_MAKE_INJECTOR( core::injector<TConfig, decltype(((TConfig*)0)->policies((concepts::injector<TConfig>*)0)), TDeps...>{ core::init{}, static_cast<TDeps&&>(args)...}); } namespace policies { namespace detail { struct type_op {}; template <class T, class = int> struct apply_impl { template <class> struct apply : T {}; }; template <template <class...> class T, class... Ts> struct apply_impl<T<Ts...>, __BOOST_DI_REQUIRES(!aux::is_base_of<type_op, T<Ts...>>::value)> { template <class TOp, class> struct apply_placeholder_impl { using type = TOp; }; template <class TOp> struct apply_placeholder_impl<_, TOp> { using type = TOp; }; template <template <class...> class TExpr, class TOp, class... TArgs> struct apply_placeholder { using type = TExpr<typename apply_placeholder_impl<TArgs, TOp>::type...>; }; template <class TArg> struct apply : apply_placeholder<T, typename TArg::type, Ts...>::type {}; }; template <class T> struct apply_impl<T, __BOOST_DI_REQUIRES(aux::is_base_of<type_op, T>::value)> { template <class TArg> struct apply : T::template apply<TArg>::type {}; }; template <class T> struct not_ : detail::type_op { template <class TArg> struct apply : aux::integral_constant<bool, !detail::apply_impl<T>::template apply<TArg>::value> {}; }; template <class... Ts> struct and_ : detail::type_op { template <class TArg> struct apply : aux::is_same<aux::bool_list<detail::apply_impl<Ts>::template apply<TArg>::value...>, aux::bool_list<aux::always<Ts>::value...>> {}; }; template <class... Ts> struct or_ : detail::type_op { template <class TArg> struct apply : aux::integral_constant<bool, !aux::is_same<aux::bool_list<detail::apply_impl<Ts>::template apply<TArg>::value...>, aux::bool_list<aux::never<Ts>::value...>>::value> {}; }; } template <class T> struct type { template <class TPolicy> struct not_allowed_by { operator aux::false_type() const { using constraint_not_satisfied = not_allowed_by; return constraint_not_satisfied{}.error(); } // clang-format off static inline aux::false_type error(_ = "type disabled by constructible policy, added by BOOST_DI_CFG or make_injector<CONFIG>!"); // clang-format on }; }; template <class> struct is_root : detail::type_op { template <class TArg> struct apply : TArg::is_root {}; }; template <class T> struct is_bound : detail::type_op { struct not_resolved {}; template <class TArg> struct apply : aux::integral_constant< bool, !aux::is_same<typename TArg::template resolve<aux::conditional_t<aux::is_same<T, _>::value, typename TArg::type, T>, typename TArg::name, not_resolved>, not_resolved>::value> {}; }; template <class T> struct is_injected : detail::type_op { template <class TArg, class U = aux::decay_t<aux::conditional_t<aux::is_same<T, _>::value, typename TArg::type, T>>> struct apply : aux::conditional_t<aux::is_class<U>::value, typename type_traits::is_injectable<U>::type, aux::true_type> {}; }; constexpr auto include_root = true; namespace operators { template <class X, class Y> inline auto operator||(const X&, const Y&) { return detail::or_<X, Y>{}; } template <class X, class Y> inline auto operator&&(const X&, const Y&) { return detail::and_<X, Y>{}; } template <class T> inline auto operator!(const T&) { return detail::not_<T>{}; } } template <bool, class T> struct constructible_impl { template <class TArg, __BOOST_DI_REQUIRES(TArg::is_root::value || T::template apply<TArg>::value) = 0> aux::true_type operator()(const TArg&) const { return {}; } template <class TArg, __BOOST_DI_REQUIRES(!TArg::is_root::value && !T::template apply<TArg>::value) = 0> aux::false_type operator()(const TArg&) const { return typename type<typename TArg::type>::template not_allowed_by<T>{}; } }; template <class T> struct constructible_impl<true, T> { template <class TArg, __BOOST_DI_REQUIRES(T::template apply<TArg>::value) = 0> aux::true_type operator()(const TArg&) const { return {}; } template <class TArg, __BOOST_DI_REQUIRES(!T::template apply<TArg>::value) = 0> aux::false_type operator()(const TArg&) const { return typename type<typename TArg::type>::template not_allowed_by<T>{}; } }; template <bool IncludeRoot = false, class T = aux::never<_>, __BOOST_DI_REQUIRES(aux::is_base_of<detail::type_op, T>::value) = 0> inline auto constructible(const T& = {}) { return constructible_impl<IncludeRoot, T>{}; } template <bool IncludeRoot = false, class T = aux::never<_>, __BOOST_DI_REQUIRES(!aux::is_base_of<detail::type_op, T>::value) = 0> inline auto constructible(const T& = {}) { return constructible_impl<IncludeRoot, detail::or_<T>>{}; } } #define __BOOST_DI_IF(cond, t, f) __BOOST_DI_IF_I(cond, t, f) #define __BOOST_DI_REPEAT(i, m, ...) __BOOST_DI_REPEAT_N(i, m, __VA_ARGS__) #define __BOOST_DI_CAT(a, ...) __BOOST_DI_PRIMITIVE_CAT(a, __VA_ARGS__) #define __BOOST_DI_EMPTY() #define __BOOST_DI_COMMA() , #define __BOOST_DI_EAT(...) #define __BOOST_DI_EXPAND(...) __VA_ARGS__ #define __BOOST_DI_SIZE(...) __BOOST_DI_CAT(__BOOST_DI_VARIADIC_SIZE_I(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, ), ) #define __BOOST_DI_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__ #define __BOOST_DI_ELEM(n, ...) __BOOST_DI_ELEM_I(n, __VA_ARGS__) #define __BOOST_DI_IS_EMPTY(...) \ __BOOST_DI_DETAIL_IS_EMPTY_IIF(__BOOST_DI_IBP(__VA_ARGS__)) \ (__BOOST_DI_DETAIL_IS_EMPTY_GEN_ZERO, __BOOST_DI_DETAIL_IS_EMPTY_PROCESS)(__VA_ARGS__) #define __BOOST_DI_DETAIL_IS_EMPTY_PRIMITIVE_CAT(a, b) a##b #define __BOOST_DI_DETAIL_IS_EMPTY_IIF(bit) __BOOST_DI_DETAIL_IS_EMPTY_PRIMITIVE_CAT(__BOOST_DI_DETAIL_IS_EMPTY_IIF_, bit) #define __BOOST_DI_DETAIL_IS_EMPTY_NON_FUNCTION_C(...) () #define __BOOST_DI_DETAIL_IS_EMPTY_GEN_ZERO(...) 0 #define __BOOST_DI_VARIADIC_SIZE_I(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, size, ...) size #define __BOOST_DI_IF_I(cond, t, f) __BOOST_DI_IIF(cond, t, f) #define __BOOST_DI_IIF_0(t, f) f #define __BOOST_DI_IIF_1(t, f) t #define __BOOST_DI_IIF_2(t, f) t #define __BOOST_DI_IIF_3(t, f) t #define __BOOST_DI_IIF_4(t, f) t #define __BOOST_DI_IIF_5(t, f) t #define __BOOST_DI_IIF_6(t, f) t #define __BOOST_DI_IIF_7(t, f) t #define __BOOST_DI_IIF_8(t, f) t #define __BOOST_DI_IIF_9(t, f) t #define __BOOST_DI_ELEM_I(n, ...) __BOOST_DI_CAT(__BOOST_DI_CAT(__BOOST_DI_ELEM, n)(__VA_ARGS__, ), ) #define __BOOST_DI_ELEM0(p1, ...) p1 #define __BOOST_DI_ELEM1(p1, p2, ...) p2 #define __BOOST_DI_ELEM2(p1, p2, p3, ...) p3 #define __BOOST_DI_ELEM3(p1, p2, p3, p4, ...) p4 #define __BOOST_DI_ELEM4(p1, p2, p3, p4, p5, ...) p5 #define __BOOST_DI_ELEM5(p1, p2, p3, p4, p5, p6, ...) p6 #define __BOOST_DI_ELEM6(p1, p2, p3, p4, p5, p6, p7, ...) p7 #define __BOOST_DI_ELEM7(p1, p2, p3, p4, p5, p6, p7, p8, ...) p8 #define __BOOST_DI_ELEM8(p1, p2, p3, p4, p5, p6, p7, p8, p9, ...) p9 #define __BOOST_DI_ELEM9(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, ...) p10 #define __BOOST_DI_REPEAT_N(i, m, ...) __BOOST_DI_REPEAT_##i(m, __VA_ARGS__) #define __BOOST_DI_REPEAT_1(m, ...) m(0, __VA_ARGS__) #define __BOOST_DI_REPEAT_2(m, ...) m(0, __VA_ARGS__) m(1, __VA_ARGS__) #define __BOOST_DI_REPEAT_3(m, ...) m(0, __VA_ARGS__) m(1, __VA_ARGS__) m(2, __VA_ARGS__) #define __BOOST_DI_REPEAT_4(m, ...) m(0, __VA_ARGS__) m(1, __VA_ARGS__) m(2, __VA_ARGS__) m(3, __VA_ARGS__) #define __BOOST_DI_REPEAT_5(m, ...) m(0, __VA_ARGS__) m(1, __VA_ARGS__) m(2, __VA_ARGS__) m(3, __VA_ARGS__) m(4, __VA_ARGS__) #define __BOOST_DI_REPEAT_6(m, ...) \ m(0, __VA_ARGS__) m(1, __VA_ARGS__) m(2, __VA_ARGS__) m(3, __VA_ARGS__) m(4, __VA_ARGS__) m(5, __VA_ARGS__) #define __BOOST_DI_REPEAT_7(m, ...) \ m(0, __VA_ARGS__) m(1, __VA_ARGS__) m(2, __VA_ARGS__) m(3, __VA_ARGS__) m(4, __VA_ARGS__) m(5, __VA_ARGS__) m(6, __VA_ARGS__) #define __BOOST_DI_REPEAT_8(m, ...) \ m(0, __VA_ARGS__) m(1, __VA_ARGS__) m(2, __VA_ARGS__) m(3, __VA_ARGS__) m(4, __VA_ARGS__) m(5, __VA_ARGS__) \ m(6, __VA_ARGS__) m(7, __VA_ARGS__) #define __BOOST_DI_REPEAT_9(m, ...) \ m(0, __VA_ARGS__) m(1, __VA_ARGS__) m(2, __VA_ARGS__) m(3, __VA_ARGS__) m(4, __VA_ARGS__) m(5, __VA_ARGS__) \ m(6, __VA_ARGS__) m(7, __VA_ARGS__) m(8, __VA_ARGS__) #define __BOOST_DI_REPEAT_10(m, ...) \ m(0, __VA_ARGS__) m(1, __VA_ARGS__) m(2, __VA_ARGS__) m(3, __VA_ARGS__) m(4, __VA_ARGS__) m(5, __VA_ARGS__) \ m(6, __VA_ARGS__) m(7, __VA_ARGS__) m(8, __VA_ARGS__) m(9, __VA_ARGS__) #if defined(__MSVC__) #define __BOOST_DI_VD_IBP_CAT(a, b) __BOOST_DI_VD_IBP_CAT_I(a, b) #define __BOOST_DI_VD_IBP_CAT_I(a, b) __BOOST_DI_VD_IBP_CAT_II(a##b) #define __BOOST_DI_VD_IBP_CAT_II(res) res #define __BOOST_DI_IBP_SPLIT(i, ...) \ __BOOST_DI_VD_IBP_CAT(__BOOST_DI_IBP_PRIMITIVE_CAT(__BOOST_DI_IBP_SPLIT_, i)(__VA_ARGS__), __BOOST_DI_EMPTY()) #define __BOOST_DI_IBP_IS_VARIADIC_C(...) 1 1 #define __BOOST_DI_IBP_SPLIT_0(a, ...) a #define __BOOST_DI_IBP_SPLIT_1(a, ...) __VA_ARGS__ #define __BOOST_DI_IBP_CAT(a, ...) __BOOST_DI_IBP_PRIMITIVE_CAT(a, __VA_ARGS__) #define __BOOST_DI_IBP_PRIMITIVE_CAT(a, ...) a##__VA_ARGS__ #define __BOOST_DI_IBP_IS_VARIADIC_R_1 1, #define __BOOST_DI_IBP_IS_VARIADIC_R___BOOST_DI_IBP_IS_VARIADIC_C 0, #define __BOOST_DI_IBP(...) \ __BOOST_DI_IBP_SPLIT(0, __BOOST_DI_IBP_CAT(__BOOST_DI_IBP_IS_VARIADIC_R_, __BOOST_DI_IBP_IS_VARIADIC_C __VA_ARGS__)) #define __BOOST_DI_IIF(bit, t, f) __BOOST_DI_IIF_OO((bit, t, f)) #define __BOOST_DI_IIF_OO(par) __BOOST_DI_IIF_I##par #define __BOOST_DI_IIF_I(bit, t, f) __BOOST_DI_IIF_##bit(t, f) #define __BOOST_DI_DETAIL_IS_EMPTY_IIF_0(t, b) b #define __BOOST_DI_DETAIL_IS_EMPTY_IIF_1(t, b) t #define __BOOST_DI_DETAIL_IS_EMPTY_PROCESS(...) __BOOST_DI_IBP(__BOOST_DI_DETAIL_IS_EMPTY_NON_FUNCTION_C __VA_ARGS__()) #else #define __BOOST_DI_IBP_SPLIT(i, ...) __BOOST_DI_PRIMITIVE_CAT(__BOOST_DI_IBP_SPLIT_, i)(__VA_ARGS__) #define __BOOST_DI_IBP_SPLIT_0(a, ...) a #define __BOOST_DI_IBP_SPLIT_1(a, ...) __VA_ARGS__ #define __BOOST_DI_IBP_IS_VARIADIC_C(...) 1 #define __BOOST_DI_IBP_IS_VARIADIC_R_1 1, #define __BOOST_DI_IBP_IS_VARIADIC_R___BOOST_DI_IBP_IS_VARIADIC_C 0, #define __BOOST_DI_IBP(...) \ __BOOST_DI_IBP_SPLIT(0, __BOOST_DI_CAT(__BOOST_DI_IBP_IS_VARIADIC_R_, __BOOST_DI_IBP_IS_VARIADIC_C __VA_ARGS__)) #define __BOOST_DI_IIF(bit, t, f) __BOOST_DI_IIF_I(bit, t, f) #define __BOOST_DI_IIF_I(bit, t, f) __BOOST_DI_IIF_II(__BOOST_DI_IIF_##bit(t, f)) #define __BOOST_DI_IIF_II(id) id #define __BOOST_DI_DETAIL_IS_EMPTY_IIF_0(t, ...) __VA_ARGS__ #define __BOOST_DI_DETAIL_IS_EMPTY_IIF_1(t, ...) t #define __BOOST_DI_DETAIL_IS_EMPTY_PROCESS(...) __BOOST_DI_IBP(__BOOST_DI_DETAIL_IS_EMPTY_NON_FUNCTION_C __VA_ARGS__()) #endif template <class, class> struct named; namespace detail { struct named_impl { template <class T> T operator=(const T&) const; }; static constexpr __BOOST_DI_UNUSED named_impl named{}; template <class T, class TName> struct combine_impl { using type = ::boost::di::v1_1_0::named<TName, T>; }; template <class T> struct combine_impl<T, aux::none_type> { using type = T; }; template <class, class> struct combine; template <class... T1, class... T2> struct combine<aux::type_list<T1...>, aux::type_list<T2...>> { using type = aux::type_list<typename combine_impl<T1, T2>::type...>; }; template <class T1, class T2> using combine_t = typename combine<T1, T2>::type; } template <class... Ts> using inject = aux::type_list<Ts...>; #define __BOOST_DI_HAS_NAME(i, ...) __BOOST_DI_IF(__BOOST_DI_IBP(__BOOST_DI_ELEM(i, __VA_ARGS__, )), 1, ) #define __BOOST_DI_HAS_NAMES(...) \ __BOOST_DI_IF(__BOOST_DI_IS_EMPTY(__BOOST_DI_REPEAT(__BOOST_DI_SIZE(__VA_ARGS__), __BOOST_DI_HAS_NAME, __VA_ARGS__)), 0, 1) #define __BOOST_DI_GEN_CTOR_IMPL(p, i) \ __BOOST_DI_IF(i, __BOOST_DI_COMMA, __BOOST_DI_EAT)() __BOOST_DI_IF(__BOOST_DI_IBP(p), __BOOST_DI_EAT p, p) #define __BOOST_DI_GEN_CTOR(i, ...) __BOOST_DI_GEN_CTOR_IMPL(__BOOST_DI_ELEM(i, __VA_ARGS__, ), i) #define __BOOST_DI_GEN_ARG_NAME(p) __BOOST_DI_GEN_ARG_NAME_IMPL p ) #define __BOOST_DI_GEN_NONE_TYPE(p) ::boost::di::v1_1_0::aux::none_type #define __BOOST_DI_GEN_ARG_NAME_IMPL(p) decltype(::boost::di::v1_1_0::detail::p) __BOOST_DI_EAT( #define __BOOST_DI_GEN_NAME_IMPL(p, i) \ __BOOST_DI_IF(i, __BOOST_DI_COMMA, __BOOST_DI_EAT) \ () __BOOST_DI_IF(__BOOST_DI_IBP(p), __BOOST_DI_GEN_ARG_NAME, __BOOST_DI_GEN_NONE_TYPE)(p) #define __BOOST_DI_GEN_NAME(i, ...) __BOOST_DI_GEN_NAME_IMPL(__BOOST_DI_ELEM(i, __VA_ARGS__, ), i) #define __BOOST_DI_INJECT_TRAITS_IMPL_0(...) \ static void ctor(__BOOST_DI_REPEAT(__BOOST_DI_SIZE(__VA_ARGS__), __BOOST_DI_GEN_CTOR, __VA_ARGS__)); \ using type __BOOST_DI_UNUSED = ::boost::di::v1_1_0::aux::function_traits_t<decltype(ctor)>; #define __BOOST_DI_INJECT_TRAITS_IMPL_1(...) \ static void ctor(__BOOST_DI_REPEAT(__BOOST_DI_SIZE(__VA_ARGS__), __BOOST_DI_GEN_CTOR, __VA_ARGS__)); \ static void name(__BOOST_DI_REPEAT(__BOOST_DI_SIZE(__VA_ARGS__), __BOOST_DI_GEN_NAME, __VA_ARGS__)); \ using type __BOOST_DI_UNUSED = \ ::boost::di::v1_1_0::detail::combine_t<::boost::di::v1_1_0::aux::function_traits_t<decltype(ctor)>, \ ::boost::di::v1_1_0::aux::function_traits_t<decltype(name)>>; #define __BOOST_DI_INJECT_TRAITS_EMPTY_IMPL(...) \ using boost_di_inject__ __BOOST_DI_UNUSED = ::boost::di::v1_1_0::aux::type_list<> #define __BOOST_DI_INJECT_TRAITS_IMPL(...) \ struct boost_di_inject__ { \ __BOOST_DI_CAT(__BOOST_DI_INJECT_TRAITS_IMPL_, __BOOST_DI_HAS_NAMES(__VA_ARGS__)) \ (__VA_ARGS__) static_assert(__BOOST_DI_SIZE(__VA_ARGS__) <= BOOST_DI_CFG_CTOR_LIMIT_SIZE, \ "Number of constructor arguments is out of range - see BOOST_DI_CFG_CTOR_LIMIT_SIZE"); \ } #define BOOST_DI_INJECT_TRAITS(...) \ __BOOST_DI_IF(__BOOST_DI_IS_EMPTY(__VA_ARGS__), __BOOST_DI_INJECT_TRAITS_EMPTY_IMPL, __BOOST_DI_INJECT_TRAITS_IMPL) \ (__VA_ARGS__) #define BOOST_DI_INJECT(T, ...) \ BOOST_DI_INJECT_TRAITS(__VA_ARGS__); \ T(__BOOST_DI_REPEAT(__BOOST_DI_SIZE(__VA_ARGS__), __BOOST_DI_GEN_CTOR, __VA_ARGS__)) BOOST_DI_NAMESPACE_END #endif #if defined(__CLANG__) #pragma clang diagnostic pop #elif defined(__GCC__) #pragma GCC diagnostic pop #endif // end <boost/io.hpp> namespace di = boost::di; class ctor { public: explicit ctor(int i) : i(i) {} int i; }; struct aggregate { double d; }; class example { public: example(aggregate a, const ctor& c) { }; }; int main() { const auto injector = di::make_injector( di::bind<int>.to(42), di::bind<double>.to(87.0) ); injector.create<example>(); }
Become a Patron
Sponsor on GitHub
Donate via PayPal
Source on GitHub
Mailing list
Installed libraries
Wiki
Report an issue
How it works
Contact the author
CE on Mastodon
About the author
Statistics
Changelog
Version tree