Full API docs available here
Bolts is a utility library for the D programming language which contains a number of static reflection utilties that query compile time entities (traits) or transform them (meta). General utilties are in the modules traits
and meta
, and more specific ones are in dedicated modules (i.e. bolts.members
provides utilities over a type's members).
- meta: has functions that result in compile time entity transofrmations, including:
Flatten
,AliasPack
,Pluck
,Zip
,FilterMembersOf
,RemoveAttributes
.
- traits: has general utitlites that can query compile time entities. including:
isFunctionOver
,isUnaryOver
,isBinaryOver
,isProperty
,hasProperty
,propertySemantics
,areCombinable
,isManifestAssignable
,isOf
,isSame
,isNullType
,StringOf
,isRefType
,isValueType
,isLiteralOf
,isLiteral
,isCopyConstructable
,isNonTriviallyCopyConstructable
,protectionLevel
,isTriviallyCopyConstructable
,hasFunctionMember
,areEquatable
,isNullSettable
,isNullTestable
,isRefDecl
,TypesOf
- members: has functions that allow you to query about the members of types
staticMembersOf
,memberFunctionsOf
,member
(not eponymous)
- range: query ranges
isSortedRange
,sortingPredicate
,CommonTypeOfRanges
- aa: has functions that act on associative arrays
isKey
(not eponymous)
- iz: super non-eponymous template that provides a lot of the functionality that's in the traits module with a different sytax that allows their usage in meta functions as well.
- experimental: contains experimental features *signatures: working implementation of type signatures *refraction: generate mixin strings to replicate a function, with some changes
Most functions here operate on any compile time entity. For example isUnaryOver
works in both these situatons:
int i;
void f(int) {}
isFunctionOver!(f, int);
isFunctionOver!(f, 3);
isFunctionOver!(f, i);
The iz
super template. Has a lot of the traits on types encapulated in one place. So if there's a trait that tells you something about a compile time entity, chances are iz
will have it. E.g:
void f(int, float, string) {}
iz!f.functionOver!(int, float, string);
iz!f.functionOver!(3, float, "");
The member
super template, found in the bolts.members
module is similar to the iz
template but works on members of types only:
import bolts.members: member;
struct S {
static void f() {}
}
assert(member!(S, "f").exists);
assert(member!(S, "f").protection == ProtectionLevel.public_);
assert(!member!(S, "f").isProperty);
Signatures are a way to enforce types to comply with other types. For example if you are making a range you can ensure your types conform to a range by mixing in a Models
template to the type that needs it. You can also use the utilities provided here to constrain functions to types that adhere to a specific signature.
interface InputRange(T) {
@property bool empty();
@property T front();
@ignoreAttributes void popFront();
}
struct MyRange {
mixin Models!(InputRange!int);
}
The above will fail to compile with something like:
source/bolts/experimental/signatures.d(310,5): Error: static assert: "Type MyRange does not comply to signature InputRange!(int)
Missing identifier empty of type bool.
Missing identifier front of type int.
Missing identifier popFront of function void().
source/bolts/experimental/signatures.d(464): <-- Signature InputRange!(int) defined here.
source/bolts/experimental/signatures.d(471): <-- Checked here."
It is sometimes necessary to create a function which is an exact copy of another function. Or sometimes it is necessary to introduce a few variations, while carrying all the other aspects. Because of function attributes, parameter storage classes and user-defined attributes, this requires building a string mixin. In addition, the mixed-in code must refer only to local names, if it is to work across module boundaires. This module facilitates the creation of such mixins.
For example, this creates a function that has a different name and return type, but retains the 'pure' attribute from the original function:
pure int answer() { return 42; }
mixin(
refract!(answer, "answer").withName("realAnswer")
.withReturnType("real")
.mixture);
static assert(is(typeof(realAnswer()) == real));
static assert(functionAttributes!realAnswer & FunctionAttribute.pure_);