Movatterモバイル変換


[0]ホーム

URL:


D Logo
Menu
Search

Language Reference

table of contents

Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page.Requires a signed-in GitHub account. This works well for small changes.If you'd like to make larger changes you may want to consider usinga local clone.

Conditional Compilation

Contents
  1. Version Condition
  2. Version Specification
    1. Predefined Versions
  3. Debug Condition
    1. Debug Statement
  4. Debug Specification
  5. Static If Condition
  6. Static Foreach
    1. break andcontinue
  7. Static Assert

Conditional compilation is the process of selecting which code to compile and which code to not compile.

ConditionalDeclaration:ConditionDeclarationBlockConditionDeclarationBlockelseDeclarationBlockCondition:DeclDefsoptConditionDeclarationBlockelse:DeclDefsopt
ConditionalStatement:ConditionNoScopeNonEmptyStatementConditionNoScopeNonEmptyStatementelseNoScopeNonEmptyStatement

If theCondition is satisfied, then the followingDeclarationBlock orStatement is compiled in. If it is not satisfied, theDeclarationBlock orStatement after the optionalelse is compiled in.

AnyDeclarationBlock orStatement that is not compiled in still must be syntactically correct.

No new scope is introduced, even if theDeclarationBlock orStatement is enclosed by{ }.

ConditionalDeclarations andConditionalStatements can be nested.

TheStaticAssert can be used to issue errors at compilation time for branches of the conditional compilation that are errors.

Condition comes in the following forms:

Condition:VersionConditionDebugConditionStaticIfCondition

Version Condition

VersionCondition:version (Identifier)version (unittest)version (assert)

Versions enable multiple versions of a module to be implemented with a single source file.

TheVersionCondition is satisfied ifIdentifier matches aversion identifier.

Theversion identifier can be set on the command line by the-version switch or in the module itself with aVersionSpecification, or they can be predefined by the compiler.

Version identifiers are in their own unique name space, they do not conflict with debug identifiers or other symbols in the module. Version identifiers defined in one module have no influence over other imported modules.

int k;version (Demo)// compile in this code block for the demo version{int i;int k;// error, k already defined    i = 3;}x = i;// uses the i declared above
version (X86){    ...// implement custom inline assembler version}else{    ...// use default, but slow, version}

Theversion(unittest) is satisfied if and only if the code is compiled with unit tests enabled (the-unittest option ondmd).

Version Specification

VersionSpecification:version =Identifier;

The version specification makes it straightforward to group a set of features under one major version, for example:

version (ProfessionalEdition){version = FeatureA;version = FeatureB;version = FeatureC;}version (HomeEdition){version = FeatureA;}...version (FeatureB){    ... implement Feature B ...}

Version identifiers or levels may not be forward referenced:

version (Foo){int x;}version = Foo;// error, Foo already used

VersionSpecifications may only appear at module scope.

While the debug and version conditions superficially behave the same, they are intended for very different purposes. Debug statements are for adding debug code that is removed for the release version. Version statements are to aid in portability and multiple release versions.

Here's an example of afull version as opposed to ademo version:

class Foo{int a, b;version(full)    {int extrafunctionality()        {            ...return 1;// extra functionality is supported        }    }else// demo    {int extrafunctionality()        {return 0;// extra functionality is not supported        }    }}

Various different version builds can be built with a parameter to version:

version(identifier)// add in version code if version// keyword is identifier{    ...version code ...}

This is presumably set by the command line as-version=identifier.

Predefined Versions

Several environmental version identifiers and identifier name spaces are predefined for consistent usage. Version identifiers do not conflict with other identifiers in the code, they are in a separate name space. Predefined version identifiers are global, i.e. they apply to all modules being compiled and imported.

Predefined Version Identifiers
Version IdentifierDescription
Host Compiler
DigitalMarsDMD (Digital Mars D)
GNUGDC (GNU D Compiler)
LDCLDC (LLVM D Compiler)
SDCSDC (Snazzy D Compiler)
Target Operating System
WindowsMicrosoft Windows systems Win32 and Win64
Win32Microsoft 32-bit Windows systems
Win64Microsoft 64-bit Windows systems
linuxAll Linux systems
AppleApple systems OSX, iOS, TVOS, WatchOS and VisionOS
OSXmacOS
iOSiOS
TVOStvOS
WatchOSwatchOS
VisionOSvisionOS
FreeBSDFreeBSD
OpenBSDOpenBSD
NetBSDNetBSD
DragonFlyBSDDragonFlyBSD
BSDAll other BSDs
SolarisSolaris
PosixAll POSIX systems (includes Linux, FreeBSD, OS X, Solaris, etc.)
AIXIBM Advanced Interactive eXecutive OS
HaikuThe Haiku operating system
SkyOSThe SkyOS operating system
SysV3System V Release 3
SysV4System V Release 4
HurdGNU Hurd
AndroidThe Android platform
EmscriptenThe Emscripten platform
PlayStationThe PlayStation platform
PlayStation4The PlayStation 4 platform
FreeStandingAn environment without an operating system (such as Bare-metal targets)
Target Environment
CygwinThe Cygwin environment
MinGWThe MinGW environment
CRuntime_BionicBionic C runtime
CRuntime_DigitalMarsDigitalMars C runtime
CRuntime_GlibcGlibc C runtime
CRuntime_MicrosoftMicrosoft C runtime
CRuntime_Muslmusl C runtime
CRuntime_Newlibnewlib C runtime
CRuntime_UClibcuClibc C runtime
CRuntime_WASIWASI C runtime
CppRuntime_ClangDeprecated, useCppRuntime_LLVM instead
CppRuntime_DigitalMarsDigitalMars C++ runtime
CppRuntime_GccDeprecated, useCppRuntime_GNU instead
CppRuntime_LLVMLLVM libc++ C++ runtime
CppRuntime_GNUGNU libstdc++ C++ runtime
CppRuntime_MicrosoftMicrosoft C++ runtime
CppRuntime_SunSun C++ runtime
Target CPU and Instruction Set
X86Intel and AMD 32-bit processors
X86_64Intel and AMD 64-bit processors
ARMThe ARM architecture (32-bit) (AArch32 et al)
ARM_ThumbARM in any Thumb mode
ARM_SoftFloatThe ARMsoft floating point ABI
ARM_SoftFPThe ARMsoftfp floating point ABI
ARM_HardFloatThe ARMhardfp floating point ABI
AArch64The Advanced RISC Machine architecture (64-bit)
AsmJSThe asm.js intermediate programming language
AVR8-bit Atmel AVR Microcontrollers
EpiphanyThe Epiphany architecture
PPCThe PowerPC architecture, 32-bit
PPC_SoftFloatThe PowerPC soft float ABI
PPC_HardFloatThe PowerPC hard float ABI
PPC64The PowerPC architecture, 64-bit
IA64The Itanium architecture (64-bit)
MIPS32The MIPS architecture, 32-bit
MIPS64The MIPS architecture, 64-bit
MIPS_O32The MIPS O32 ABI
MIPS_N32The MIPS N32 ABI
MIPS_O64The MIPS O64 ABI
MIPS_N64The MIPS N64 ABI
MIPS_EABIThe MIPS EABI
MIPS_SoftFloatThe MIPSsoft-float ABI
MIPS_HardFloatThe MIPShard-float ABI
MSP430The MSP430 architecture
NVPTXThe Nvidia Parallel Thread Execution (PTX) architecture, 32-bit
NVPTX64The Nvidia Parallel Thread Execution (PTX) architecture, 64-bit
RISCV32The RISC-V architecture, 32-bit
RISCV64The RISC-V architecture, 64-bit
SPARCThe SPARC architecture, 32-bit
SPARC_V8PlusThe SPARC v8+ ABI
SPARC_SoftFloatThe SPARC soft float ABI
SPARC_HardFloatThe SPARC hard float ABI
SPARC64The SPARC architecture, 64-bit
S390The System/390 architecture, 32-bit
SystemZThe System Z architecture, 64-bit
HPPAThe HP PA-RISC architecture, 32-bit
HPPA64The HP PA-RISC architecture, 64-bit
SHThe SuperH architecture, 32-bit
WebAssemblyThe WebAssembly virtual ISA (instruction set architecture), 32-bit
WASIThe WebAssembly System Interface
XtensaThe Xtensa Architecture, 32-bit
AlphaThe Alpha architecture
Alpha_SoftFloatThe Alpha soft float ABI
Alpha_HardFloatThe Alpha hard float ABI
Byte Order (endianess)
LittleEndianByte order, least significant first
BigEndianByte order, most significant first
Executable and Link Format
ELFv1Elf version 1
ELFv2Elf version 2
Miscellaneous
D_BetterCD as Better C code (command line switch-betterC) is being generated
D_ExceptionsException handling is supported. Evaluates tofalse when compiling with command line switch-betterC
D_ModuleInfoModuleInfo is supported. Evaluates tofalse when compiling with command line switch-betterC
D_TypeInfoRuntime type information (a.k.aTypeInfo) is supported. Evaluates tofalse when compiling with command line switch-betterC
D_CoverageCode coverage analysis instrumentation (command line switch-cov) is being generated
D_DdocDdoc documentation (command line switch-D) is being generated
D_InlineAsm_X86Inline assembler for X86 is implemented
D_InlineAsm_X86_64Inline assembler for X86-64 is implemented
D_LP64Pointers are 64 bits (command line switch-m64). (Do not confuse this with C's LP64 model)
D_X32Pointers are 32 bits, but words are still 64 bits (x32 ABI) (This can be defined in parallel toX86_64)
D_HardFloatThe target hardware has a floating-point unit
D_SoftFloatThe target hardware does not have a floating-point unit
D_PICPosition Independent Code (command line switch-fPIC) is being generated
D_PIEPosition Independent Executable (command line switch-fPIE) is being generated
D_SIMDVector extensions (via__simd) are supported
D_AVXAVX Vector instructions are supported
D_AVX2AVX2 Vector instructions are supported
D_Version2This is a D version 2 compiler
D_NoBoundsChecksArray bounds checks are disabled (command line switch-boundscheck=off)
D_ObjectiveCThe target supports interfacing with Objective-C
D_ProfileGCGC allocations being profiled (command line switch-profile=gc)
D_OptimizedCompiling with enabled optimizations (command line switch-O)
CoreDefined when building the standard runtime
StdDefined when building the standard library
unittestUnit tests are enabled (command line switch-unittest)
assertChecks are being emitted forAssertExpressions
D_PreConditionsChecks are being emitted forin contracts
D_PostConditionsChecks are being emitted forout contracts
D_InvariantsChecks are being emitted forclass invariants andstruct invariants
Special Cases
noneNever defined; used to just disable a section of code
allAlways defined; used as the opposite ofnone

The following identifiers are defined, but are deprecated:

Predefined Version Identifiers (deprecated)
Version IdentifierDescription
darwinThe Darwin operating system; useOSX instead
ThumbARM in Thumb mode; useARM_Thumb instead
S390XThe System/390X architecture, 64-bit; useSystemZ instead

Others will be added as they make sense and new implementations appear.

To allow for future growth of the language, the version identifier namespace beginning with "D_" is reserved for identifiers indicating D language specification or new feature conformance. Further, all identifiers derived from the ones listed above by appending any character(s) are reserved. This means that e.g.ARM_foo andWindows_bar are reserved whilefoo_ARM andbar_Windows are not.

Predefined version identifiers from this list cannot be set from the command line or from version statements. (This prevents things like bothWindows andlinux being simultaneously set.)

Compiler vendor specific versions can be predefined if the trademarked vendor identifier prefixes it, as in:

version(DigitalMars_funky_extension){    ...}

It is important to use the right version identifier for the right purpose. For example, use the vendor identifier when using a vendor specific feature. Use the operating system identifier when using an operating system specific feature, etc.

Debug Condition

DebugCondition:debugdebug (Identifier)

Two versions of programs are commonly built, a release build and a debug build. The debug build includes extra error checking code, test harnesses, pretty-printing code, etc. The debug statement conditionally compiles in its statement body. It is D's way of what in C is done with#ifdef DEBUG /#endif pairs.

Thedebug condition is satisfied when the-debug switch is passed to the compiler.

Thedebug (Identifier) condition is satisfied when the debug identifier matchesIdentifier.

class Foo{int a, b;debug:int flag;}

Debug Statement

AConditionalStatement that has aDebugCondition is called aDebugStatement.DebugStatements have relaxed semantic checks in thatpure,@nogc,nothrow and@safe checks are not done. Neither doDebugStatements influence the inference ofpure,@nogc,nothrow and@safe attributes.

Undefined Behavior: Since these checks are bypassed, it is up to the programmer to ensure the code is correct. For example, throwing an exception in anothrow function is undefined behavior.
Best Practices: This enables the easy insertion of code to provide debugging help, by bypassing the otherwise stringent attribute checks. Never ship release code that hasDebugStatements enabled.

Debug Specification

DebugSpecification:debug =Identifier;

Debug identifiers are set either by the command line switch-debug or by aDebugSpecification.

Debug specifications only affect the module they appear in, they do not affect any imported modules. Debug identifiers are in their own namespace, independent from version identifiers and other symbols.

It is illegal to forward reference a debug specification:

debug(foo) writeln("Foo");debug = foo;// error, foo used before set

DebugSpecifications may only appear at module scope.

Various different debug builds can be built with a parameter to debug:

debug(identifier) { }// add in debug code if debug keyword is identifier

These are presumably set by the command line as and-debug=identifier.

Static If Condition

StaticIfCondition:static if (AssignExpression)

AssignExpression is implicitly converted to a boolean type, and is evaluated at compile time. The condition is satisfied if it evaluates totrue. It is not satisfied if it evaluates tofalse.

It is an error ifAssignExpression cannot be implicitly converted to a boolean type or if it cannot be evaluated at compile time.

StaticIfConditions can appear in module, class, template, struct, union, or function scope. In function scope, the symbols referred to in theAssignExpression can be any that can normally be referenced by an expression at that point.

constint i = 3;int j = 4;staticif (i == 3)// ok, at module scopeint x;class C{constint k = 5;staticif (i == 3)// okint x;elselong x;staticif (j == 3)// error, j is not a constantint y;staticif (k == 5)// ok, k is in current scopeint z;}
template Int(int i){staticif (i == 32)alias Int =int;elsestaticif (i == 16)alias Int =short;elsestaticassert(0);// not supported}Int!(32) a;// a is an intInt!(16) b;// b is a shortInt!(17) c;// error, static assert trips

AStaticIfCondition differs from anIfStatement in the following ways:

  1. It can be used to conditionally compile declarations, not just statements.
  2. It does not introduce a new scope even if{ } are used for conditionally compiled statements.
  3. For unsatisfied conditions, the conditionally compiled code need only be syntactically correct. It does not have to be semantically correct.
  4. It must be evaluatable at compile time.

Static Foreach

StaticForeachDeclaration:StaticForeachDeclarationBlockStaticForeach:DeclDefsopt
StaticForeachStatement:StaticForeachNoScopeNonEmptyStatement
StaticForeach:staticAggregateForeachstaticRangeForeach

static foreach expands itsDeclarationBlock orDeclDefs into a series of declarations, each of which may reference anyForeachType symbols declared.

staticforeach (i; [0, 1, 2, 3]){pragma(msg, i);}

static foreach supports multipleForeachType variables in cases where the correspondingforeach statement supports them. (In this case,static foreach generates a compile-time sequence of tuples, and the tuples are subsequently unpacked during iteration).

staticforeach (i, v; ['a', 'b', 'c', 'd']){staticassert(i + 'a' == v);}

Like bodies ofConditionalDeclarations, astatic foreach body does not introduce a new scope. Therefore, it can be used to add declarations to an existing scope:

import std.range : iota;staticforeach (i; iota(0, 3)){mixin(`enum x`, i,` = i;`);}pragma(msg, x0," ", x1," ", x2);// 0 1 2

Inside a function, if a new scope is desired for each expansion, use another set of braces:

void fun(){staticforeach (s; ["hi","hey","hello"])    {{enum len = s.length;// local to each iterationstaticassert(len <= 5);    }}staticassert(!is(typeof(len)));}

static foreach supports sequence expansionlikeforeach.

break andcontinue

Asstatic foreach is a code generation construct and not a loop,break andcontinue cannot be used to change control flow within it. Instead of breaking or continuing a suitable enclosing statement, such an usage yields an error (this is to prevent misunderstandings).

int test(int x){int r = -1;switch(x)    {staticforeach (i; 0 .. 5)        {case i:                r = i;break;// error        }default:break;    }return r;}staticforeach (i; 0 .. 10){staticassert(test(i) == (i < 5 ? i : -1));}

An explicitbreak/continue label can be used to avoid this limitation. (Note thatstatic foreach itself cannot be broken nor continued even if it is explicitly labeled.)

int test(int x){int r = -1;    Lswitch:switch(x)    {staticforeach (i; 0 .. 5)        {case i:                r = i;break Lswitch;        }default:break;    }return r;}staticforeach (i; 0 .. 10){staticassert(test(i) == (i < 5 ? i : -1));}

Static Assert

StaticAssert:static assert (ArgumentList) ;

The firstAssignExpression is evaluated at compile time, and converted to a boolean value. If the value is true, the static assert is ignored. If the value is false, an error diagnostic is issued and the compile fails.

On failure, any subsequentAssignExpressions will each be converted to string and then concatenated. The resulting string will be printed out along with the error diagnostic.

UnlikeAssertExpressions,StaticAsserts are always checked and evaluated by the compiler unless they appear in an unsatisfied conditional.

void foo(){if (0)    {assert(0);// never tripsstaticassert(0);// always trips    }version (BAR)    {    }else    {staticassert(0);// trips when version BAR is not defined    }}

StaticAssert is useful tool for drawing attention to conditional configurations not supported in the code.

Contract Programming
Traits
Copyright © 1999-2025 by theD Language Foundation | Page generated byDdoc on Fri Oct 10 22:16:58 2025

[8]ページ先頭

©2009-2025 Movatter.jp