当前位置:网站首页>D compile time reflection
D compile time reflection
2022-06-25 05:49:00 【fqbqrr】
original text Compile time reflection
send D
Metaprogramming is flexible and powerful .
Find out the validity of the expression :
__traits( compiles, a + b );
is( typeof( a + b ) );
__traits(compiles,expr)
and is(typeof(expr))
Both need lexical validity expression
. But the latter does not check whether compile
, Instead, check for the presence of Expression type
.
Mission : Create accept and include with numbers " be similar
“ An array of elements ” be similar
" object , Return average ( Mathematical expectation ) function
template isNumArray(T)
{
enum isNumArray = __traits(compiles,
{
auto a = T.init[0];
static if( !__traits(isArithmetic,a) ) //
{
static assert( __traits( compiles, a=a+a ) ); //
static assert( __traits( compiles, a=a-a ) ); //
static assert( __traits( compiles, a=a*.0f ) ); // Add, subtract, multiply and divide
}
auto b = T.init.length;
static assert( is( typeof(b) : size_t ) );
});
}
auto mean(T)( T arr ) @property if( isNumArray!T )
in {
assert( arr.length > 0 ); } body
{
// Average .
auto ret = arr[0] - arr[0];
foreach( i; 0 .. arr.length )
ret = ret + arr[i];
return ret * ( 1.0f / arr.length );
}
usage :
import std.string : format;
struct Vec2
{
float x=0, y=0;
auto opBinary(string op)( auto ref const Vec2 rhs ) const
if( op == "+" || op == "-" )
{
mixin( format( "return Vec2( x %1$s rhs.x, y %1$s rhs.y );", op ) ); }
auto opBinary(string op)( float rhs ) const
if( op == "*" )
{
return Vec2( x * rhs, y * rhs ); }
}
struct Triangle
{
Vec2 p1, p2, p3;
auto opIndex(size_t v)
{
switch(v)
{
case 0: return p1;
case 1: return p2;
case 2: return p3;
default: throw new Exception( " only 3 Elements , Don't cross the line " );
}
}
static pure size_t length() {
return 3; }
}
void main()
{
auto f = [ 1.0f, 2, 3 ];
assert( f.mean == 2.0f ); //
auto v = [ Vec2(1,6), Vec2(2,7), Vec2(3,5) ];
assert( v.mean == Vec2(2,6) ); //
auto t = Triangle( Vec2(1,6), Vec2(2,7), Vec2(3,5) );
assert( t.mean == Vec2(2,6) ); //
}
// Lack of detail , Do not use .
is(…)
is
The structure is very powerful .
is( T );
Next , Check T type :
is( T == Type );
is( T : Type );
// New alias
is( T ident : Type );
is( T ident == Type );
Example :
void foo(T)( T value )
{
static if( is( T U : long ) ) //
alias Num = U; //
else
alias Num = long; //
}
Still can
is( T == limit );
here , limit
yes :struct,union,class,interface,enum,function,delegate,const,immutable,shared
etc. . therefore , Check T Whether it is structure , union , class
etc. .
You can also combine checks with aliases :
is( T ident == limit )
Another interesting trick : Pattern matching
type
is( T == TypeTempl, TemplParams... );
is( T : TypeTempl, TemplParams... );
is( T ident == TypeTempl, TemplParams... );
is( T ident : TypeTempl, TemplParams... );
here ,TypeTempl
Is to describe ( Reunite with ) type ,TemplParams
It's the composition TypeTempl
The elements of .
struct Foo(size_t N, T) if( N > 0 ) {
T[N] data; }
struct Bar(size_t N, T) if( N > 0 ) {
float[N] arr; T value; }
void func(U)( U val )
{
static if( is( U E == S!(N,T), alias S, size_t N, T ) )
{
pragma(msg, "Foo The same structure : ", E );
pragma(msg, "S: ", S.stringof);
pragma(msg, "N: ", N);
pragma(msg, "T: ", T);
}
else static if( is( U T : T[X], X ) )
{
pragma(msg, " Associative array T[X]: ", U );
pragma(msg, "T(value): ", T);
pragma(msg, "X(key): ", X);
}
else static if( is( U T : T[N], size_t N ) )
{
pragma(msg, " Static array T[N]: ", U );
pragma(msg, "T(value): ", T);
pragma(msg, "N(length): ", N);
}
else pragma(msg, "other: ", U );
pragma(msg,"");
}
void main()
{
func( Foo!(10,double).init );
func( Bar!(12,string).init );
func( [ "hello": 23 ] );
func( [ 42: "habr" ] );
func( Foo!(8,short).init.data );
func( 0 );
}
Output :
Foo Like structure : Foo!(10LU, double)
S: Foo(ulong N, T) if (N > 0)
N: 10LU
T: double
Foo Like structure : Bar!(12LU, string)
S: Bar(ulong N, T) if (N > 0)
N: 12LU
T: string
Associative array T[X]: int[string]
T(value): int
X(key): string
Associative array T[X]: string[int]
T(value): string
X(key): int
Static array T[N]: short[8]
T(value): short
N(length): 8LU
other: int
__traits(keyWord, …)
term | Meaning |
---|---|
compiles | Whether the expression is valid |
isAbstractClass | abstract class |
isArithmetic | Arithmetic Type ( Numbers and enumerations ) |
isAssociativeArray | Associative array |
isFinalClass | End class ( Cannot inherit ) |
isPOD | Old data This can be done by simply Copy byte by byte To initialize the type ( Hide fields , No use Destructor ) |
isNested | Nested Type ( Dependent on context ) |
isFloating | Floating point numbers ( Including the plural ) |
isIntegral | Integers |
isScalar | Scalar type ( Numbers , enumeration , The pointer ),__vector(int[4]) It is also a scalar type |
isStaticArray | Static array |
isUnsigned | just |
isVirtualMethod | Virtual method |
isVirtualFunction | Virtual functions |
isAbstractFunction | Abstract functions |
isFinalFunction | Final function |
isStaticFunction | Static functions |
isOverrideFunction | overloaded function |
isRef | reference parameter |
isOut | Output Parameters |
isLazy | Idle parameter ( By demand value ) |
isSame | Whether the expressions are the same |
hasMember | class / structure Is there a Field / Method , The first parameter is type ( or Type object ), The second parameter is Field / Method name strand . |
Example :
class A {
class B {
} }
pragma(msg, __traits(isNested,A.B));
// It's nesting
void f1()
{
auto f2() {
return 12; }
pragma(msg,__traits(isNested,f2)); // true
}
auto f1()
{
auto val = 12;
struct S {
auto f2() {
return val; } }
return S.init;
}
pragma(msg,__traits(isNested,typeof(f1()))); // true
//
struct Foo {
float value; }
pragma(msg, __traits(hasMember, Foo, "value")); // true
pragma(msg, __traits(hasMember, Foo, "data")); // false
About isFunction and isVirtualMethod and isVirtualFunction The difference between
For the sake of clarity , I wrote a test to show the difference
import std.stdio, std.string;
string test(alias T)()
{
string ret;
ret ~= is( typeof(T) == delegate ) ? "D " :
is( typeof(T) == function ) ? "F " : "? ";
ret ~= __traits(isVirtualMethod,T) ? "m|" : "-|";
ret ~= __traits(isVirtualFunction,T) ? "v|" : "-|";
ret ~= __traits(isAbstractFunction,T) ? "a|" : "-|";
ret ~= __traits(isFinalFunction,T) ? "f|" : "-|";
ret ~= __traits(isStaticFunction,T) ? "s|" : "-|";
ret ~= __traits(isOverrideFunction,T) ? "o|" : "-|";
return ret;
}
class A
{
static void stat() {
}
void simple1() {
}
void simple2() {
}
private void simple3() {
}
abstract void abstr() {
}
final void fnlNOver() {
}
}
class B : A
{
override void simple1() {
}
final override void simple2() {
}
override void abstr() {
}
}
class C : B
{
final override void abstr() {
}
}
interface I
{
void abstr();
final void fnl() {
}
}
struct S {
void func(){
} }
void globalFunc() {
}
void main()
{
A a; B b; C c; I i; S s;
writeln( " id T m|v|a|f|s|o|" );
writeln( "--------------------------" );
writeln( " lambda: ", test!(x=>x) );
writeln( " function: ", test!((){
return 3; }) );
writeln( " delegate: ", test!((){
return b; }) );
writeln( " s.func: ", test!(s.func) );
writeln( " global: ", test!(globalFunc) );
writeln( " a.stat: ", test!(a.stat) );
writeln( " a.simple1: ", test!(a.simple1) );
writeln( " a.simple2: ", test!(a.simple2) );
writeln( " a.simple3: ", test!(a.simple3) );
writeln( " a.abstr: ", test!(a.abstr) );
writeln( "a.fnlNOver: ", test!(a.fnlNOver) );
writeln( " b.simple1: ", test!(b.simple1) );
writeln( " b.simple2: ", test!(b.simple2) );
writeln( " b.abstr: ", test!(b.abstr) );
writeln( " c.abstr: ", test!(c.abstr) );
writeln( " i.abstr: ", test!(i.abstr) );
writeln( " i.fnl: ", test!(i.fnl) );
}
result :
id T m|v|a|f|s|o|
--------------------------
lambda: ? -|-|-|-|-|-|
function: ? -|-|-|-|s|-|
delegate: D -|-|-|-|-|-|
s.func: F -|-|-|-|-|-|
global: F -|-|-|-|s|-|
a.stat: F -|-|-|-|s|-|
a.simple1: F m|v|-|-|-|-|
a.simple2: F m|v|-|-|-|-|
a.simple3: F -|-|-|-|-|-|
a.abstr: F m|v|a|-|-|-|
a.fnlNOver: F -|v|-|f|-|-|
b.simple1: F m|v|-|-|-|o|
b.simple2: F m|v|-|f|-|o|
b.abstr: F m|v|-|-|-|o|
c.abstr: F m|v|-|f|-|o|
i.abstr: F m|v|a|-|-|-|
i.fnl: F -|-|a|f|-|-|
isVirtualMethod
Yes Overloadable or overloaded
All contents are returned true
. If Not overloaded
function , And it was final
Of , Is not a virtual method , It's a virtual function .
I can't explain λ
and function ( Function type literal )
Nearby question marks , They failed Function or delegate
test .
hinder , Provide examples , See the document for details :
enum Foo;
class Bar {
@(42) @Foo void func() pure @nogc @property {
} }
pragma(msg, __traits(getAttributes, Bar.func)); //
@?Foo float value;
pragma(msg, __traits(getAttributes, value)); //
//
enum Foo;
class Bar {
@(42) @Foo void func() pure @nogc @property {
} }
pragma(msg, __traits(getFunctionAttributes, Bar.func));
//
class Bar {
float value; }
Bar bar;
__traits(getMember, bar, "value") = 10;
//
import std.stdio;
class A
{
void foo( float ) {
}
void foo( string ) {
}
int foo( int ) {
return 12; }
}
void main()
{
foreach( f; __traits(getOverloads, A, "foo") )
writeln( typeof(f).stringof );
}
// result
void(float _param_0)
void(string _param_0)
int(int _param_0)
//
class A
{
float val1;
A val2;
void* val3;
void[] val4;
void function() val5;
void delegate() val6;
}
enum bm =
0b101011000;
//||||||||+-
//|||||||+--
//||||||+--- float val1
//|||||+---- A val2
//||||+----- void* val3
//|||+------ void[] val4
//||+------- void[] val4
//|+-------- void function() val5
//+--------- void delegate() val6
//0---------- void delegate() val6( The first 1 individual 0)
static assert( __traits(getPointerBitmap,A) == [10*size_t.sizeof, bm] );
struct B {
float x, y, z; }
static assert( __traits(getPointerBitmap,B) == [3*float.sizeof, 0] );
//
import std.stdio;
struct B
{
float value;
void func() {
}
}
alias F = B.func;
void main()
{
writeln( __traits(parent,writeln).stringof ); // module stdio
writeln( typeid( typeof( __traits(parent,F).value ) ) ); // float
}
Template and signature constraints
The simplest form of a template function is as follows :
void func(T)( T val ) {
... }
however Template parameter
There are also forms , such as is
structure , Used for inspection Implicit conversion
, Even for Matching mode
. combination Signature constraints
, Create interesting Overload template function
Combine :
import std.stdio;
void func(T:long)( T val ) {
writeln( "number" ); }
void func(T: U[E], U, E)( T val ) if( is( E == string ) ) {
writeln( " With string key AA" ); }
void func(T: U[E], U, E)( T val ) if( is( E : long ) ) {
writeln( " With numeric keys AA" ); }
void main()
{
func( 120 ); // Numbers
func( ["hello": 12] ); // strand AA
func( [10: 12] ); // Numbers AA
}
边栏推荐
- 2.20 learning content
- Aiot project that is an introduction to the basics of the Internet of things and can be implemented in practice
- MySQL -- optimize query statements and use not in with cases
- What changes have taken place in the project file after SAP ui5 tools ran the Fiori add deploy config command
- SAP ui5 tutorial for beginners part XXVI - detailed steps for using OData service with mock server trial version
- Word quickly makes multiple single-sided table labels, number plates, etc
- JSON Library Tutorial from scratch (II): parsing digital learning and sorting notes
- Deep analysis of epoll reactor code
- Jenkins installation and configuration
- Go language map sorting (key/value sorting)
猜你喜欢
Technology inventory: past, present and future of Message Oriented Middleware
Code learning-cvpr2020 unsupervised domain adaptive semantic segmentation: intra advance
SSRF-lab
Create a complete binary tree in array order
Stack and Queue
Volatile and JMM memory models
[golang] leetcode intermediate - Search rotation sort array & search two-dimensional matrix II
MySQL operation JSON
C language - minesweeping
Configuration file ui5 local in SAP ui5 tools Configuration points of yaml
随机推荐
Use of pytorch tensorboard
ArcGIS Engine + Visual Studio installation tutorial
1.6.3 use tcpdump to observe DNS communication process
Interface learning
What changes have taken place in the project file after SAP ui5 tools ran the Fiori add deploy config command
Go language map sorting (key/value sorting)
SAP ui5 beginner tutorial No. 27 - unit test tool quNit introduction trial version for SAP ui5 application
Solve some prompt codes that pychar cannot recognize selenium
16 application problem solving
Charles and iPhone capture
SAP ui5 date type sap ui. model. type. Analysis of date parsing format
What happens when you use "-fno exceptions", "new T"- With “-fno-exceptions”, what happens with “new T”?
Introduction to MySQL test run test framework
"APEC industry +" biov Tech talks about the cross-border of Chinese biotechnology enterprises and "Pratt & Whitney Kangyu" | apec-hub public welfare
C style string
MySQL -- optimize query statements and use not in with cases
Transformations of pytorch torch torch vision
Introduction to the main features of kyma when the cloud native application runs
Multithreading and thread pool
The locally developed SAP ui5 application is deployed to the ABAP server to perform error analysis