ããã«ã¡ã¯ãHabrïŒ
仿¥ã¯ãDã§ã®ã¡ã¿ããã°ã©ãã³ã°ãéåžžã«æè»ã§åŒ·åãªãã®ãã€ãŸãã³ã³ãã€ã«æã®ãªãã¬ã¯ã·ã§ã³ã«ã€ããŠèª¬æããŸãã Dã䜿çšãããšãããã°ã©ããŒã¯ãã³ã³ãã€ã©ãŒãæäœããæ
å ±ããããªãããŒãªæ¹æ³ã§è¡šç€ºããã®ã§ã¯ãªããçŽæ¥äœ¿çšã§ããŸãã ã§ã¯ãã³ã³ãã€ã©ã¯ã©ã®ãããªæ
å ±ãååŸããã©ã®ããã«äœ¿çšã§ããŸããïŒ
ããããæãäžè¬çãªäœ¿ç𿹿³ããå§ããŸããã-åŒã®åŠ¥åœæ§ã調ã¹ãïŒ
__traits( compiles, a + b )
__traitsïŒcompilesãexprïŒãšisïŒtypeofïŒexprïŒïŒã¯ãèªåœã®èгç¹ããæå¹ãªåŒexprãæåŸ
ããŸãïŒããšãã°ãåŒ12thbã¯æå¹ãªèå¥åã§ã¯ãªããããã³ã³ãã€ã©ãŒã¯ãšã©ãŒãã¹ããŒããŸãïŒã ãããã¯åãããã«åäœããŸããã1ã€ã®åŸ®åŠãªã€ããªãã®ãŒã®éãããããŸã-isïŒtypeofïŒexprïŒïŒã¯ã³ã³ãã€ã«èœåããã§ãã¯ããŸããããåŒã®ã¿ã€ãã®ååšããã§ãã¯ããŸãã ãããã£ãŠãçè«çã«ã¯ãåãç¥ãããšãã§ããç¶æ³ã¯å¯èœã§ãããããã€ãã®èŠåã«ãã£ãŠãã®æ§é ãã³ã³ãã€ã«ããããšã¯ã§ããŸããã å®éã«ã¯ãç§ã¯ãã®ãããªç¶æ³ã«ééããããš
ã¯ãããŸããïŒããããããã
ã¯ãŸã èšèªã«ãªã£
ãŠããªãã§ãããïŒã
䜿çšäŸã¿ã¹ã¯ïŒæ°å€ã«ãé¡äŒŒãããèŠçŽ ãå«ãé
åã«ãé¡äŒŒããããªããžã§ã¯ããåãå
¥ãã颿°ãäœæããå¹³åå€ïŒmatãExpectationïŒãè¿ããŸãã
解決çïŒ
template isNumArray(T) { enum isNumArray = __traits(compiles, { auto a = T.init[0]; // opIndex int static if( !__traits(isArithmetic,a) ) // , { static assert( __traits( compiles, a=a+a ) ); // static assert( __traits( compiles, a=aa ) ); // static assert( __traits( compiles, a=a*.0f ) ); // float } auto b = T.init.length; // length static assert( is( typeof(b) : size_t ) ); }); } auto mean(T)( T arr ) @property if( isNumArray!T ) in { assert( arr.length > 0 ); } body { // arr[index] arr.length // , arr[index] auto ret = arr[0] - arr[0]; // (0) foreach( i; 0 .. arr.length ) ret = ret + arr[i]; // += return ret * ( 1.0f / arr.length ); }
äœ¿çšæ³ïŒ
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; // var[index] auto opIndex(size_t v) { switch(v) { case 0: return p1; case 1: return p2; case 2: return p3; default: throw new Exception( "triangle have only three elements" ); } } static pure size_t length() { return 3; } } void main() { auto f = [ 1.0f, 2, 3 ]; assert( f.mean == 2.0f ); // float auto v = [ Vec2(1,6), Vec2(2,7), Vec2(3,5) ]; assert( v.mean == Vec2(2,6) ); // user-defined auto t = Triangle( Vec2(1,6), Vec2(2,7), Vec2(3,5) ); assert( t.mean == Vec2(2,6) ); // user-defined }
èŠå ïŒäŸïŒisNumArrayïŒã®ã³ãŒãã¯ã詳现ãèæ
®ããªããã䜿çšããªãã§ãã ããïŒopIndexã¯å®æ°åç
§ãè¿ãããšãã§ãããããå²ãåœãŠæäœã¯ã§ããŸããïŒã
æ§é ã¯ïŒ...ïŒ
èšèšã«ã¯ããªã倧ããªæ©èœã»ããããããŸãã
is( T );
ããã«ããã¹ãŠã®å Žåã«ãããŠãã¿ã€ãTã®æå³çåŠ¥åœæ§ããã§ãã¯ãããŸãã
is( T == Type ); // T Type is( T : Type ); // T Type
æ°ãããšã€ãªã¢ã¹ãäœæãããã©ãŒã ããããŸãã
is( T ident )
ãã®å Žåãã¿ã€ãTãæå¹ã§ããã°ãidentãšããååã§ãšã€ãªã¢ã¹ãäœæãããŸãã ãããããã®ãããªãã©ãŒã ãäœããã®æ€èšŒãšçµã¿åãããããšã¯ããè峿·±ãã§ããã
is( T ident : Type ); is( T ident == Type );
äŸ void foo(T)( T value ) { static if( is( TU : long ) )
ãŸããã¿ã€ããäœã§ãããã確èªãããã®ä¿®é£ŸåãèŠã€ããããšãã§ããŸã
is( T == Specialization )
ãã®å ŽåãSpecializationã¯å¯èœãªå€ã®1ã€ã§ãïŒstructãunionãclassãinterfaceãenumãfunctionãdelegateãconstãimmutableãsharedã ãããã£ãŠãã¿ã€ãTãæ§é äœãå
±çšäœãã¯ã©ã¹ãªã©ã§ãããã©ããããã§ãã¯ãããŸãã ãããŠãæ€èšŒãšãšã€ãªã¢ã¹ã®å®£èšãçµã¿åããããã©ãŒã ããããŸã
is( T ident == Specialization )
å¥ã®è峿·±ãããªãã¯ããããŸã-ãã¿ãŒã³ãããã³ã°ã¿ã€ãã§ãã
is( T == TypeTempl, TemplParams... ); is( T : TypeTempl, TemplParams... ); // alias' is( T ident == TypeTempl, TemplParams... ); is( T ident : TypeTempl, TemplParams... );
ãã®å ŽåãTypeTemplã¯ã¿ã€ãïŒè€åïŒã®èª¬æã§ãããTemplParamsã¯TypeTemplãæ§æããèŠçŽ ã§ãã
äŸ 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( UE == S!(N,T), alias S, size_t N, T ) ) { pragma(msg, "struct like Foo: ", E ); pragma(msg, "S: ", S.stringof); pragma(msg, "N: ", N); pragma(msg, "T: ", T); } else static if( is( UT : T[X], X ) ) { pragma(msg, "associative array T[X]: ", U ); pragma(msg, "T(value): ", T); pragma(msg, "X(key): ", X); } else static if( is( UT : 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 ); }
ã³ã³ãã€ã«åºå
struct like Foo: Foo!(10LU, double) S: Foo(ulong N, T) if (N > 0) N: 10LU T: double struct like Foo: 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ã...ïŒ
ããŒã¯ãŒãã®åŸã®ã»ãšãã©ã®__traitsã¯ãåŒãåŒæ°ïŒãŸãã¯ã³ã³ãåºåãã®ãªã¹ãïŒãšããŠåãåãããã®çµæãèŠä»¶ã«æºæ ããŠãããã©ããã確èªãããã¹ããåæ ããããŒã«å€ãè¿ããŸãã åŒã¯ãåèªäœãŸãã¯åã®å€ãè¿ãå¿
èŠããããŸãã ä»ã®éšåã¯1ã€ã®åŒæ°ãåããããŒã«å€ïŒåºæ¬çã«ã¯äœãã®ãªã¹ãïŒãããæçãªãã®ãè¿ããŸãã
__traitsã®æ€èšŒïŒ
- ã³ã³ãã€ã«-æå¹ãªåŒ
- isAbstractClass-æœè±¡ã¯ã©ã¹
- isArithmetic-ç®è¡åïŒæ°å€ãšåæïŒ
- isAssociativeArray-飿³é
å
- isFinalClass-æçµã¯ã©ã¹ïŒç¶æ¿ã§ããŸããïŒ
- isPOD-ãã¬ãŒã³ãªãŒã«ãããŒã¿-åçŽãªãã€ãã³ããŒã§åæåã§ããã¿ã€ãïŒé衚瀺ãã£ãŒã«ãããã¹ãã©ã¯ã¿ã¯çŠæ¢ãããŠããŸãïŒ
- isNested-ãã¹ããããã¿ã€ãïŒã³ã³ããã¹ãäŸåïŒ
äŸ class A { class B {} } pragma(msg, __traits(isNested,AB));
void f1() { auto f2() { return 12; } pragma(msg,__traits(isNested,f2));
auto f1() { auto val = 12; struct S { auto f2() { return val; } }
- isFloating-æµ®åå°æ°ç¹æ°ïŒè€çŽ æ°ãå«ãïŒ
- isIntegral-æŽæ°
- isScalarã¯ã¹ã«ã©ãŒåïŒæ°å€ãåæããã€ã³ã¿ãŒïŒã§ããã__ vectorïŒint [4]ïŒãã¹ã«ã©ãŒåã§ã
- isStaticArray-éçé
å
- isUnsigned-笊å·ãªãæŽæ°
- isVirtualMethod-ä»®æ³ã¡ãœããïŒãªãŒããŒããŒãã§ãããã®ïŒ
- isVirtualFunction-ä»®æ³é¢æ°ïŒä»®æ³é¢æ°ã®ããŒãã«ã«ãããã®ïŒ
- isAbstractFunction-æœè±¡é¢æ°
- isFinalFunction-æçµé¢æ°
- isStaticFunction-éç颿°
- isOverrideFunction-ãªãŒããŒããŒãããã颿°
- isRef-åŒæ°ãªãã¡ã¬ã³ã¹
- isOut-åºååŒæ°ãªã³ã¯
- isLazy-é
å»¶åŒæ°ïŒãªã³ããã³ãã§èšç®ïŒ
- isSame-åãåŒã§ã
- hasMember-ã¯ã©ã¹/æ§é ã«ãã®ãããªãã£ãŒã«ã/ã¡ãœããããããæåã®åŒæ°ã§åïŒãŸãã¯åãªããžã§ã¯ãïŒãåãå
¥ãã2çªç®ã®è¡ã§ãã£ãŒã«ã/ã¡ãœããåãåãå
¥ããŸã
äŸ struct Foo { float value; } pragma(msg, __traits(hasMember, Foo, "value")); // true pragma(msg, __traits(hasMember, Foo, "data")); // false
is <Some>颿°ãšisVirtualMethodãšisVirtualFunctionã®éãã«ã€ããŠæç¢ºã«ããããã«ãéãã瀺ãå°ããªãã¹ããäœæããŸãã
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) ); }
çµæ
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ã¯ããªããŒãã§ãããã®ããŸãã¯ãã§ã«ãªãŒããŒããŒããããŠãããã®ã«å¯ŸããŠtrueãè¿ããŸãã 颿°ããªãŒããŒããŒããããŠããããå
ã
æçµçãªãã®ã§ãã£ãå Žåãããã¯ä»®æ³ã¡ãœããã§ã¯ãªããä»®æ³é¢æ°ã«ãªããŸãã
ã©ã ããšé¢æ°ïŒé¢æ°åã®ãªãã©ã«ïŒã«ã€ããŠã®çå笊ã«ã€ããŠã¯èª¬æã§ããŸããããäžæãªçç±ã«ããã颿°ãŸãã¯ããªã²ãŒãã®ãããã®ãã¹ãã«ãåæ ŒããŸããã§ããã
äœããè¿ãïŒ
- identifier-1ã€ã®åŒæ°ãåããæååãè¿ããŸãïŒ.stringofãšåæ§ïŒ
- getAliasThis-åã«åthisãããå ŽåãåãŸãã¯åã®ãªããžã§ã¯ããåãå
¥ããæååã®ã¿ãã«ãšããŠè¿ããŸããããã§ãªãå Žåã¯ç©ºã®ã¿ãã«ïŒèŠããŠããéããããã¯åã«å¯ŸããŠ1ã€ã®ãšã€ãªã¢ã¹ã®ã¿ãµããŒããããŸãïŒ
- getAttributes-èå¥åãåãå
¥ãããŠãŒã¶ãŒã宣èšãã屿§ã®ã¿ãã«ãè¿ããŸãïŒUDA-ãŠãŒã¶ãŒå®çŸ©ã®å±æ§ïŒ
äŸ enum Foo; class Bar { @â(42) @âFoo void func() pure @ânogc @âproperty {} } pragma(msg, __traits(getAttributes, Bar.func));
- getFunctionAttributesã¯ã颿°ã颿°ãªãã©ã«ã颿°ãžã®ãã€ã³ã¿ãŒãåããæååã®åœ¢åŒã§å±æ§ã®ã¿ãã«ãè¿ããŸãïŒããã«ã¯UDAã¯å«ãŸããŠããŸããïŒã Pureãnothrowã@ nogcã@ propertyã@ systemã@ trustedã@ safeãããã³refããµããŒããããŠããŸãïŒé¢æ°ããªã³ã¯ãè¿ãå ŽåïŒãã¯ã©ã¹/æ§é äœã«ã¯ãconstãimmutableãinoutãããã³sharedããããŸãã é åºã¯å®è£
ã«äŸåããä¿¡é Œããããšã¯ã§ããŸããã
äŸ enum Foo; class Bar { @â(42) @âFoo void func() pure @ânogc @âproperty {} } pragma(msg, __traits(getFunctionAttributes, Bar.func)); // tuple("pure", "@ânogc", "@âproperty", "@âsystem")
- getMember-hasMemberãšåãåŒæ°ãåããŸããããããä»ããæžã蟌ã¿ãšåçã§ã
äŸ class Bar { float value; } Bar bar; __traits(getMember, bar, "value") = 10;
- getOverloads-ã¯ã©ã¹/æ§é /ã¢ãžã¥ãŒã«ãšãã¯ã©ã¹/æ§é /ã¢ãžã¥ãŒã«å
ã®é¢æ°åã«äžèŽããæååãåãåãããã®é¢æ°ã®ãã¹ãŠã®ãªãŒããŒããŒãã®ã¿ãã«ãè¿ããŸã
äŸ 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 ); }
çµæ
void(float _param_0) void(string _param_0) int(int _param_0)
- getPointerBitmap-åãåãå
¥ããé
åsize_tãè¿ããŸãã æåã®æ°ã¯ãã®ã¿ã€ãã®ãªããžã§ã¯ããå ãããã€ãæ°ã§ããã2çªç®ã¯ãã®ã¿ã€ãã®ãªããžã§ã¯ãå
ã®ã¬ããŒãžã³ã¬ã¯ã¿ãŒã«ãã£ãŠç®¡çããããã€ã³ã¿ãŒã®äœçœ®ã瀺ããŸã
äŸ class A { // , 1 , GC: // monitor, , 1, GC: float val1; // 1, GC: A val2; // 1, GC: void* val3; // 1, GC: void[] val4; // 2 { GC: , GC: } void function() val5; // 1, GC: void delegate() val6; // 2 { GC: , GC: } } enum bm = 0b101011000; // ||||||||+- // |||||||+-- monitor // ||||||+--- float val1 // |||||+---- A val2 // ||||+----- void* val3 // |||+------ void[] val4 // ||+------- void[] val4 // |+-------- void function() val5 // +--------- void delegate() val6 // 0---------- void delegate() val6 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] ); // B ,
- getProtection-æåãåãå
¥ããæååãè¿ããŸããå¯èœãªãªãã·ã§ã³ïŒãpublicãããprivateãããprotectedãããexportããããã³ãpackageã
- getVirtualMethods-ã¯ã©ã¹ãšé¢æ°åã®æååãååŸããgetOverloadsãšã»ãŒåæ§ã«æ©èœãã颿°ã®ã¿ãã«ãè¿ããŸã
- getVirtualFunctionsã¯getVirtualMethodsãšåãã§ãããäœããªãŒããŒããŒãããªãã£ãæçµé¢æ°ãå«ãŸããŠããŸãã
- getUnitTests-ã¯ã©ã¹/æ§é /ã¢ãžã¥ãŒã«ãåãå
¥ãããŠããããã¹ãã®ã¿ãã«ãéç颿°ãšããŠè¿ããŸããUDAã¯ä¿åãããŸã
- parent-æž¡ããã芪æåãè¿ããŸã
äŸ import std.stdio; struct B { float value; void func() {} } alias F = B.func; void main() { writeln( __traits(parent,writeln).stringof );
- classInstanceSize-ã¯ã©ã¹ãååŸããã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ãå æãããã€ãæ°ãè¿ããŸã
- getVirtualIndex-颿°ïŒã¯ã©ã¹ã¡ãœããïŒãåããã¯ã©ã¹ã®ä»®æ³é¢æ°ããŒãã«ã®ã€ã³ããã¯ã¹ïŒptrdiff_tïŒãè¿ããŸãã 颿°ãæçµã§ãããäœãåå®çŸ©ããªãã£ãå Žåã-1ãè¿ããŸã
- allMembers-åãåããç¹°ãè¿ããçµã¿èŸŒã¿ããããã£ïŒsizeofãªã©ïŒãªãã§ãã¹ãŠã®ãã£ãŒã«ããšã¡ãœããã®ååãå«ãæååã®ã¿ãã«ãè¿ããŸããã¯ã©ã¹ã®å Žåã¯ãåºæ¬ã¯ã©ã¹ã®ãã£ãŒã«ããšã¡ãœãããå«ãŸããŸã
- derivedMembers-åãåãåãããã¹ãŠã®ãã£ãŒã«ããšã¡ãœããã®ååãå«ãæååã®ã¿ãã«ããç¹°ãè¿ããªãã§ãçµã¿èŸŒã¿ããããã£ãªãã§ãåºåºã¯ã©ã¹ã®ãã£ãŒã«ããšã¡ãœãããªãã§ïŒã¯ã©ã¹çšïŒ
眲åãã³ãã¬ãŒããšå¶é
æãåçŽãªå®è¡ã§ã¯ããã³ãã¬ãŒã颿°ã¯æ¬¡ã®ããã«ãªããŸã
void func(T)( T val ) { ... }
ããããåãããã«ããã³ãã¬ãŒãåŒæ°ã«ã¯ãæé»çãªãã£ã¹ãããã§ãã¯ããããã®ãããã«ã¯ãã¿ãŒã³ãããã³ã°ã®ããã®æ§é ããããŸãã ãããšçœ²åã®å¶éãçµã¿åãããŠããªãŒããŒããŒãããããã³ãã¬ãŒã颿°ã®è峿·±ãçµã¿åãããäœæã§ããŸãã
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( "AA with string key" ); } void func(T: U[E], U, E)( T val ) if( is( E : long ) ) { writeln( "AA with num key" ); } void main() { func( 120 );
æšæºã©ã€ãã©ãª
å€ãã®ããã±ãŒãžã®æšæºã©ã€ãã©ãªã«ã¯ãåãäœããã®åäœããµããŒããããã©ããã確èªããããã«ãã³ãã¬ãŒããæ£åšããŠããŸãïŒããšãã°ããã®ããã±ãŒãžã®é¢æ°ã䜿çšããããã«å¿
èŠã§ãïŒã ãã ããç¹å¥ãªæ©èœãå®è£
ããªãããã±ãŒãžãããã€ããããŸãããçµã¿èŸŒã¿ã®__traitsã®äŸ¿å©ãªã©ãããŒãšãã³ã³ãã©ã€ã¢ã³ã¹ããã§ãã¯ããããã®è¿œå ã®ã¢ã«ãŽãªãºã ãæäŸããŸãã
- std.traits-å€ãã®ãã§ãã¯ãšã©ãããŒãå«ãŸããŠããŸã
- std.typetuple-ã¿ã€ãã¿ãã«ãæäœããããã®ãã³ãã¬ãŒã
ãŸãšã
ãããã®ã¢ãããŒãããã¹ãŠçµã¿åãããŠãæ³åãçµ¶ããã»ã©è€éã§æè»ãªã¡ã¿ããã°ã©ã æ§æãäœæã§ããŸãã ããããDèšèªã¯ãæãæè»ãªã¡ã¿ããã°ã©ãã³ã°ã¢ãã«ã®1ã€ãå®è£
ããŠããŸãã ãããã誰ãããã®ã³ãŒãïŒããããããªãèªèº«ïŒãèªã¿ããã®ãããªæ§æãéåžžã«åé¡ã«ãªãããšãçè§£ã§ããããšãåžžã«èŠããŠãããŠãã ããã åžžã«ãããã«ãªããå°é£ãªç¬éã«ãã£ãšã³ã¡ã³ãããããã«ããŠãã ããã