struct Vector(size_t N,T) { T[N] data; this( in T[N] vals... ) { data = vals; } }
auto a = Vector!(3,float)(1,2,3);
alias Vector3f = Vector!(3,float); auto a = Vector3f(1,2,3);
alias Vector3(T) = Vector!(3,T); auto a = Vector3!float(1,2,3); auto b = Vector3!int(1,2,3);
struct Vector(size_t N,T) if( N > 0 ) { ... }
Vector!(0,float) a;
vector.d(10): Error: template instance vector.Vector!(0, float) does not match template declaration Vector(ulong N, T) if (N > 0)
struct Vector(size_t N,T) if( N > 0 ) { ... auto opBinary(string op)( in Vector!(N,T) b ) const { Vector!(N,T) ret; foreach( i; 0 .. N ) mixin( "ret.data[i] = data[i] " ~ op ~ " b.data[i];" ); return ret; } }
auto a = Vector3!float(1,2,3); auto b = Vector3!float(2,3,4); auto c = Vector3!float(5,6,7); c = a + b / c * a;
... auto opBinary(string op,E)( in Vector!(N,E) b ) const if( is( typeof( mixin( "T.init" ~ op ~ "E.init" ) ) : T ) ) { ...} ...
auto opBinary(string op,E)( in E b ) const if( is( typeof( mixin( "T.init" ~ op ~ "E.init" ) ) : T ) ) { ...}
void foo(size_t N)( in float[N] arr ) { ... }
struct Vector(size_t N,T) if (N > 0) { T[N] data; alias data this; ... }
auto a = Vector3!float(1,2,3); a[2] = 10;
auto a = Vector2!string("hell", "habr"); auto b = Vector2!string("o", "ahabr"); writeln( a ~ b ); // ["hello", "habrahabr"]
import std.algorithm; import std.math; struct Vector(size_t N,T) if (N > 0) { ... static if( is( typeof( T.init * T.init ) == T ) ) { const @property { auto len2() { return reduce!((r,v)=>r+=v*v)( data.dup ); } static if( is( typeof( sqrt(T.init) ) ) ) { auto len() { return sqrt( len2 ); } auto e() { return this / len; } } } } }
... import std.traits; struct Vector(size_t N,T) if (N > 0) { this(E)( in Vector!(N,E) b ) // if( is( typeof( cast(T)(E.init) ) ) ) { foreach( i; 0 .. N ) data[i] = cast(T)(b[i]); } ... static if( isNumeric!T ) { auto len(E=CommonType!(T,float))() { return sqrt( cast(E)len2 ); } auto e(E=CommonType!(T,float))() { return Vector!(N,E)(this) / len!E; } } ... }
CommonType!(int,float) a; // float a; CommonType!(double,float) b; // double b;
auto a = Vector3f(1,2,3); auto b = Vector2f(1,2); auto c = Vector!(8,float)( 0, a, 4, b, 3 );
struct Vector(size_t N,T) if (N > 0) { ... this(E...)( in E vals ) { size_t i = 0; foreach( v; vals ) i += fillData( data, i, v ); } ... }
size_t fillData(size_t N,T,E)( ref T[N] data, size_t no, E val ) { static if( isNumeric!E ) { data[no] = cast(T)val; return 1; } else static if( isStaticArray!E && isNumeric!(typeof(E.init[0])) ) { foreach( i, v; val ) data[no+i] = v; return val.length; } else static if( isVector!E ) { foreach( i, v; val.data ) data[no+i] = cast(T)v; return val.data.length; } else static assert(0,"unkompatible type"); }
template isVector(E) { enum isVector = is( typeof( impl(E.init) ) ); void impl(size_t N,T)( Vector!(N,T) x ); }
... auto x() const @property { return data[0]; } ...
class A { void opDispatch(string str)( int x ) { writeln( str, ": ", x ); } } auto a = new A; a.hello( 4 ); // hello: 4
enum string SEP1=" "; enum string SEP2="|"; struct Vector(size_t N,T,alias string AS) if ( N > 0 && ( AS.length == 0 || isCompatibleAccessStrings(N,AS,SEP1,SEP2) ) ) { ... }
/// compatible for creating access dispatches pure bool isCompatibleArrayAccessStrings( size_t N, string str, string sep1="", string sep2="|" ) in { assert( sep1 != sep2 ); } body { auto strs = str.split(sep2); foreach( s; strs ) if( !isCompatibleArrayAccessString(N,s,sep1) ) return false; string[] fa; foreach( s; strs ) fa ~= s.split(sep1); foreach( ref v; fa ) v = strip(v); foreach( i, a; fa ) foreach( j, b; fa ) if( i != j && a == b ) return false; return true; } /// compatible for creating access dispatches pure bool isCompatibleArrayAccessString( size_t N, string str, string sep="" ) { return N == getAccessFieldsCount(str,sep) && isArrayAccessString(str,sep); } /// pure bool isArrayAccessString( in string as, in string sep="", bool allowDot=false ) { if( as.length == 0 ) return false; auto splt = as.split(sep); foreach( i, val; splt ) if( !isValueAccessString(val,allowDot) || canFind(splt[0..i],val) ) return false; return true; } /// pure size_t getAccessFieldsCount( string str, string sep ) { return str.split(sep).length; } /// pure ptrdiff_t getIndex( string as, string arg, string sep1="", string sep2="|" ) in { assert( sep1 != sep2 ); } body { foreach( str; as.split(sep2) ) foreach( i, v; str.split(sep1) ) if( arg == v ) return i; return -1; } /// pure bool oneOfAccess( string str, string arg, string sep="" ) { auto splt = str.split(sep); return canFind(splt,arg); } /// pure bool oneOfAccessAll( string str, string arg, string sep="" ) { auto splt = arg.split(""); return all!(a=>oneOfAccess(str,a,sep))(splt); } /// pure bool oneOfAnyAccessAll( string str, string arg, string sep1="", string sep2="|" ) in { assert( sep1 != sep2 ); } body { foreach( s; str.split(sep2) ) if( oneOfAccessAll(s,arg,sep1) ) return true; return false; } /// check symbol count for access to field pure bool isOneSymbolPerFieldForAnyAccessString( string str, string sep1="", string sep2="|" ) in { assert( sep1 != sep2 ); } body { foreach( s; str.split(sep2) ) if( isOneSymbolPerFieldAccessString(s,sep1) ) return true; return false; } /// check symbol count for access to field pure bool isOneSymbolPerFieldAccessString( string str, string sep="" ) { foreach( s; str.split(sep) ) if( s.length > 1 ) return false; return true; } pure { bool isValueAccessString( in string as, bool allowDot=false ) { return as.length > 0 && startsWithAllowedChars(as) && (allowDot?(all!(a=>isValueAccessString(a))(as.split("."))):allowedCharsOnly(as)); } bool startsWithAllowedChars( in string as ) { switch(as[0]) { case 'a': .. case 'z': goto case; case 'A': .. case 'Z': goto case; case '_': return true; default: return false; } } bool allowedCharsOnly( in string as ) { foreach( c; as ) if( !allowedChar(c) ) return false; return true; } bool allowedChar( in char c ) { switch(c) { case 'a': .. case 'z': goto case; case 'A': .. case 'Z': goto case; case '0': .. case '9': goto case; case '_': return true; default: return false; } } }
struct Vector( size_t N, T, alias string AS="" ) if( N > 0 && ( isCompatibleArrayAccessStrings(N,AS,SEP1,SEP2) || AS.length == 0 ) ) { ... static if( AS.length > 0 ) // { @property { // : ax = by; ref T opDispatch(string v)() if( getIndex(AS,v,SEP1,SEP2) != -1 ) { mixin( format( "return data[%d];", getIndex(AS,v,SEP1,SEP2) ) ); } // T opDispatch(string v)() const if( getIndex(AS,v,SEP1,SEP2) != -1 ) { mixin( format( "return data[%d];", getIndex(AS,v,SEP1,SEP2) ) ); } // , , e static if( isOneSymbolPerFieldForAnyAccessString(AS,SEP1,SEP2) ) { // auto a = b.xy; // typeof(a) == Vector!(2,int,"x y"); // auto a = b.xx; // typeof(a) == Vector!(2,int,""); auto opDispatch(string v)() const if( v.length > 1 && oneOfAnyAccessAll(AS,v,SEP1,SEP2) ) { mixin( format( `return Vector!(v.length,T,"%s")(%s);`, isCompatibleArrayAccessString(v.length,v)?v.split("").join(SEP1):"", array( map!(a=>format( `data[%d]`,getIndex(AS,a,SEP1,SEP2)))(v.split("")) ).join(",") )); } // a.xy = b.zw; auto opDispatch( string v, U )( in U b ) if( v.length > 1 && oneOfAnyAccessAll(AS,v,SEP1,SEP2) && isCompatibleArrayAccessString(v.length,v) && ( isCompatibleVector!(v.length,T,U) || ( isDynamicVector!U && is(typeof(T(U.datatype.init))) ) ) ) { foreach( i; 0 .. v.length ) data[getIndex(AS,""~v[i],SEP1,SEP2)] = T( b[i] ); return opDispatch!v; } } } }
Source: https://habr.com/ru/post/246763/
All Articles