Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1531

Show
Ignore:
Timestamp:
05/22/10 00:10:16 (15 years ago)
Author:
rsinfu
Message:

Added AutoImplement? to std.typecons.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/traits.d

    r1530 r1531  
    453453    enum Variadic variadicFunctionStyle = 
    454454        determineVariadicity!( Unqual!(FunctionTypeOf!(func)) )(); 
    455455} 
    456456 
    457457private Variadic determineVariadicity(Func)() 
    458458{ 
    459459    // TypeFuncion --> CallConvention FuncAttrs Arguments ArgClose Type 
    460460    immutable callconv = functionLinkage!(Func); 
    461461    immutable mfunc = mangledName!(Func); 
    462462    immutable mtype = mangledName!(ReturnType!(Func)); 
    463     debug assert(mfunc[$ - mtype.length .. $] == mtype); 
     463    debug assert(mfunc[$ - mtype.length .. $] == mtype, mfunc ~ "|" ~ mtype); 
    464464 
    465465    immutable argclose = mfunc[$ - mtype.length - 1]; 
    466466    final switch (argclose) 
    467467    { 
    468468        case 'X': return Variadic.TYPESAFE; 
    469469        case 'Y': return (callconv == "C") ? Variadic.C : Variadic.D; 
    470470        case 'Z': return Variadic.NO; 
    471471    } 
    472472} 
    473473 
     
    547547 
    548548    class Callable { int opCall(int) { return 0; } } 
    549549    auto call = new Callable; 
    550550    static assert(is( FunctionTypeOf!(call) == typeof(test) )); 
    551551 
    552552    struct StaticCallable { static int opCall(int) { return 0; } } 
    553553    StaticCallable stcall_val; 
    554554    StaticCallable* stcall_ptr; 
    555555    static assert(is( FunctionTypeOf!(stcall_val) == typeof(test) )); 
    556556    static assert(is( FunctionTypeOf!(stcall_ptr) == typeof(test) )); 
     557 
     558    interface Overloads { 
     559        void test(string); 
     560        real test(real); 
     561        int  test(); 
     562        int  test() @property; 
     563    } 
     564    alias TypeTuple!(__traits(getVirtualFunctions, Overloads, "test")) ov; 
     565    alias FunctionTypeOf!(ov[0]) F_ov0; 
     566    alias FunctionTypeOf!(ov[1]) F_ov1; 
     567    alias FunctionTypeOf!(ov[2]) F_ov2; 
     568    alias FunctionTypeOf!(ov[3]) F_ov3; 
     569    static assert(is(F_ov0* == void function(string))); 
     570    static assert(is(F_ov1* == real function(real))); 
     571    static assert(is(F_ov2* == int function())); 
     572    static assert(is(F_ov3* == int function() @property)); 
    557573} 
    558574 
    559575 
    560576//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    561577// Aggregate Types 
    562578//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    563579 
    564580/*** 
    565581 * Get the types of the fields of a struct or class. 
    566582 * This consists of the fields that take up memory space, 
     
    12651281    interface J : I { J test(); } 
    12661282    interface K     { K test(int); } 
    12671283    class B : I, K 
    12681284    { 
    12691285        K test(int) { return this; } 
    12701286        B test() { return this; } 
    12711287        static void test(string) { } 
    12721288    } 
    12731289    class C : B, J 
    12741290    { 
    1275         C test() { return this; } 
     1291        override C test() { return this; } 
    12761292    } 
    12771293    alias MemberFunctionsTuple!(C, "test") test; 
    12781294    static assert(test.length == 2); 
    12791295    static assert(is(FunctionTypeOf!(test[0]) == FunctionTypeOf!(C.test))); 
    12801296    static assert(is(FunctionTypeOf!(test[1]) == FunctionTypeOf!(B.test))); 
    12811297    alias MemberFunctionsTuple!(C, "noexist") noexist; 
    12821298    static assert(noexist.length == 0); 
    12831299 
    12841300    interface L { int prop() @property; } 
    12851301    alias MemberFunctionsTuple!(L, "prop") prop; 
     
    20682084    auto c = new C; 
    20692085 
    20702086    static assert( isCallable!(c)); 
    20712087    static assert( isCallable!(S)); 
    20722088    static assert( isCallable!(c.opCall)); 
    20732089    static assert( isCallable!(I.value)); 
    20742090    static assert(!isCallable!(I)); 
    20752091} 
    20762092 
    20772093 
     2094/** 
     2095Exactly the same as the builtin traits: 
     2096$(D ___traits(_isAbstractFunction, method)). 
     2097 */ 
     2098template isAbstractFunction(alias method) 
     2099{ 
     2100    enum bool isAbstractFunction  = __traits(isAbstractFunction, method); 
     2101} 
     2102 
     2103 
     2104 
    20782105//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    20792106// General Types 
    20802107//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    20812108 
    20822109/** 
    20832110Removes all qualifiers, if any, from type $(D T). 
    20842111 
    20852112Example: 
    20862113---- 
    20872114static assert(is(Unqual!(int) == int)); 
     
    23362363            } 
    23372364            m_upb *= 10; 
    23382365        } 
    23392366    } 
    23402367 
    23412368    return s; 
    23422369} 
    23432370 
    23442371unittest 
    23452372{ 
     2373    typedef int MyInt; 
    23462374    class C { int value() @property { return 0; } } 
    23472375    static assert(mangledName!(int) == int.mangleof); 
    23482376    static assert(mangledName!(C) == C.mangleof); 
     2377    static assert(mangledName!(MyInt)[$ - 7 .. $] == "T5MyInt"); 
    23492378    static assert(mangledName!(C.value)[$ - 12 .. $] == "5valueMFNdZi"); 
    23502379    static assert(mangledName!(mangledName) == "3std6traits11mangledName"); 
    23512380    static assert(mangledName!(removeDummyEnvelope) == 
    23522381            "_D3std6traits19removeDummyEnvelopeFAyaZAya"); 
     2382} 
     2383 
     2384 
     2385/* 
     2386workaround for [BUG 2234] "allMembers does not return interface members" 
     2387 */ 
     2388package template traits_allMembers(Agg) 
     2389{ 
     2390    static if (is(Agg == class) || is(Agg == interface)) 
     2391        alias NoDuplicates!( __traits(allMembers, Agg), 
     2392                    traits_allMembers_ifaces!(InterfacesTuple!(Agg)) ) 
     2393                traits_allMembers; 
     2394    else 
     2395        alias TypeTuple!(__traits(allMembers, Agg)) traits_allMembers; 
     2396} 
     2397private template traits_allMembers_ifaces(I...) 
     2398{ 
     2399    static if (I.length > 0) 
     2400        alias TypeTuple!( __traits(allMembers, I[0]), 
     2401                    traits_allMembers_ifaces!(I[1 .. $]) ) 
     2402                traits_allMembers_ifaces; 
     2403    else 
     2404        alias TypeTuple!() traits_allMembers_ifaces; 
     2405} 
     2406 
     2407unittest 
     2408{ 
     2409    interface I { void test(); } 
     2410    interface J : I { } 
     2411    interface K : J { } 
     2412    alias traits_allMembers!(K) names; 
     2413    static assert(names.length == 1); 
     2414    static assert(names[0] == "test"); 
    23532415} 
    23542416 
    23552417 
    23562418 
    23572419// XXX Select & select should go to another module. (functional or algorithm?) 
    23582420 
    23592421/** 
    23602422Aliases itself to $(D T) if the boolean $(D condition) is $(D true) 
    23612423and to $(D F) otherwise. 
    23622424 
  • trunk/phobos/std/typecons.d

    r1520 r1531  
    11// Written in the D programming language. 
    22 
    33/** 
    44This module implements a variety of type constructors, i.e., templates 
    55that allow construction of new, useful general-purpose types. 
    66 
    77Macros: 
    88 
    99WIKI = Phobos/StdVariant 
     10EM   = <em>$0</em> 
    1011  
    1112Synopsis: 
    1213 
    1314---- 
    1415// value tuples 
    1516alias Tuple!(float, "x", float, "y", float, "z") Coord; 
    1617Coord c; 
    1718c.field[1] = 1;   // access by index 
    1819c.z = 1;          // access by given name 
    1920alias Tuple!(string, string) DicEntry; // names can be omitted 
     
    4041    r.foo();  
    4142    // rebind r to refer to another object 
    4243    r = w2; 
    4344} 
    4445---- 
    4546 
    4647Copyright: Copyright Andrei Alexandrescu 2008 - 2009. 
    4748License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. 
    4849Authors:   $(WEB erdani.org, Andrei Alexandrescu), 
    4950           $(WEB bartoszmilewski.wordpress.com, Bartosz Milewski), 
    50            Don Clugston 
    51            Masahiro Nakagawa 
     51           Don Clugston, 
     52           Masahiro Nakagawa, 
     53           Shin Fujishiro 
    5254 
    5355         Copyright Andrei Alexandrescu 2008 - 2009. 
    5456Distributed under the Boost Software License, Version 1.0. 
    5557   (See accompanying file LICENSE_1_0.txt or copy at 
    5658         http://www.boost.org/LICENSE_1_0.txt) 
    5759*/ 
    5860module std.typecons; 
    5961import std.array, std.contracts, std.conv, std.metastrings, std.traits, std.typetuple; 
    6062 
    6163/** 
     
    13741376    int x = 5; 
    13751377    auto a = NullableRef!(int)(&x); 
    13761378    assert(!a.isNull); 
    13771379    assert(a == 5); 
    13781380    a = 42; 
    13791381    assert(!a.isNull); 
    13801382    assert(a == 42); 
    13811383} 
    13821384 
    13831385+/ 
     1386 
     1387 
     1388/** 
     1389$(D AutoImplement), by default, automatically implements all abstract member 
     1390functions in the class or interface $(D Base) as do-nothing functions. 
     1391 
     1392-------------------- 
     1393abstract class Base 
     1394{ 
     1395    int m_value; 
     1396    this(int v) { m_value = v; } 
     1397    int value() @property { return m_value; } 
     1398 
     1399    abstract real realValue() @property; 
     1400    abstract void doSomething(); 
     1401} 
     1402 
     1403void main() 
     1404{ 
     1405    auto obj = new AutoImplement!Base(42); 
     1406    writeln(obj.value);     // prints "42" 
     1407 
     1408    // Abstract functions are implemented as do-nothing: 
     1409    writeln(obj.realValue); // prints "NaN" 
     1410    obj.doSomething();      // does nothing 
     1411} 
     1412-------------------- 
     1413 
     1414The behavior can be customized with the parameters. 
     1415 
     1416Params: 
     1417  how  = A template which determines _how functions will be 
     1418         implemented/overridden. 
     1419 
     1420         Two arguments are passed to $(D how): the first one is the $(D Base), 
     1421         and the second one is an alias to a function to be implemented.  Then 
     1422         $(D how) must return a implemented function body as a string. 
     1423 
     1424         The generated function body can use these keywords: 
     1425         $(UL 
     1426            $(LI $(D a0), $(D a1), &hellip;: arguments passed to the function;) 
     1427            $(LI $(D args): a tuple of the arguments;) 
     1428            $(LI $(D self): an alias to the function itself;) 
     1429            $(LI $(D parent): an alias to the overridden function (if any).) 
     1430         ) 
     1431 
     1432        You may want to use templated property functions (instead of Implicit 
     1433        Template Properties) to generate complex functions: 
     1434-------------------- 
     1435// Prints log messages for each call to overridden functions. 
     1436string generateLogger(C, alias fun)() @property 
     1437{ 
     1438    enum qname = C.stringof ~ "." ~ __traits(identifier, fun); 
     1439    string stmt; 
     1440 
     1441    stmt ~= q{ struct Importer { import std.stdio; } }; 
     1442    stmt ~= `Importer.writeln$(LPAREN)"Log: ` ~ qname ~ `(", args, ")"$(RPAREN);`; 
     1443    static if (!__traits(isAbstractFunction, fun)) 
     1444    { 
     1445        static if (is(typeof(return) == void)) 
     1446            stmt ~= q{ parent(args); }; 
     1447        else 
     1448            stmt ~= q{ 
     1449                auto r = parent(args); 
     1450                Importer.writeln("--> ", r); 
     1451                return r; 
     1452            }; 
     1453    } 
     1454    return stmt; 
     1455} 
     1456-------------------- 
     1457 
     1458  what = A template which determines _what functions should be 
     1459         implemented/overridden. 
     1460 
     1461         An argument is passed to $(D what): an alias to a non-final member 
     1462         function in $(D Base).  Then $(D what) must return a boolean value. 
     1463         Return $(D true) to indicate that the passed function should be 
     1464         implemented/overridden. 
     1465 
     1466-------------------- 
     1467// Sees if fun returns something. 
     1468template hasValue(alias fun) 
     1469{ 
     1470    enum bool hasValue = !is(ReturnType!(fun) == void); 
     1471} 
     1472-------------------- 
     1473 
     1474 
     1475Note: 
     1476 
     1477Generated code is inserted in the scope of $(D std.typecons) module.  Thus, 
     1478any useful functions outside $(D std.typecons) cannot be used in the generated 
     1479code.  To workaround this problem, you may $(D import) necessary things in a 
     1480local struct, as done in the $(D generateLogger()) template in the above 
     1481example. 
     1482 
     1483 
     1484BUGS: 
     1485 
     1486$(UL 
     1487 $(LI Variadic arguments to constructors are not forwarded to super.) 
     1488 $(LI Deep interface inheritance causes compile error with messages like 
     1489      "Error: function std.typecons._AutoImplement!(Foo)._AutoImplement.bar 
     1490      does not override any function".  [$(BUGZILLA 2525), $(BUGZILLA 3525)] ) 
     1491 $(LI The $(D parent) keyword is actually a delegate to the super class' 
     1492      corresponding member function.  [$(BUGZILLA 2540)] ) 
     1493 $(LI Using $(D alias) template parameter in $(D how) and/or $(D what) may 
     1494      cause strange compile error.  Use template tuple parameter instead to 
     1495      workaround this problem.  [$(BUGZILLA 4217)] ) 
     1496) 
     1497 */ 
     1498class AutoImplement( Base, 
     1499        alias how = generateEmptyFunction, alias what = isAbstractFunction ) 
     1500    : Base 
     1501{ 
     1502    private alias AutoImplement_Helper!( 
     1503            "autoImplement_helper_", "Base", Base, how, what ) 
     1504             autoImplement_helper_; 
     1505    override mixin(autoImplement_helper_.code); 
     1506} 
     1507 
     1508/* 
     1509 * Code-generating stuffs are encupsulated in this helper template so that 
     1510 * namespace pollusion, which can cause name confliction with Base's public 
     1511 * members, should be minimized. 
     1512 */ 
     1513private template AutoImplement_Helper(string myName, string baseName, 
     1514        Base, alias generateMethodBody, alias cherrypickMethod) 
     1515{ 
     1516private static: 
     1517    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1518    // Internal stuffs 
     1519    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1520 
     1521    // this would be deprecated by std.typelist.Filter 
     1522    template staticFilter(alias pred, lst...) 
     1523    { 
     1524        alias staticFilterImpl!(pred, lst).result staticFilter; 
     1525    } 
     1526    template staticFilterImpl(alias pred, lst...) 
     1527    { 
     1528        static if (lst.length > 0) 
     1529        { 
     1530            alias staticFilterImpl!(pred, lst[1 .. $]).result tail; 
     1531            // 
     1532            static if (true && pred!(lst[0])) 
     1533                alias TypeTuple!(lst[0], tail) result; 
     1534            else 
     1535                alias tail result; 
     1536        } 
     1537        else 
     1538            alias TypeTuple!() result; 
     1539    } 
     1540 
     1541    // Returns function overload sets in the class C, filtered with pred. 
     1542    template enumerateOverloads(C, alias pred) 
     1543    { 
     1544        alias enumerateOverloadsImpl!(C, pred, traits_allMembers!(C)).result 
     1545                enumerateOverloads; 
     1546    } 
     1547    template enumerateOverloadsImpl(C, alias pred, names...) 
     1548    { 
     1549        static if (names.length > 0) 
     1550        { 
     1551            alias staticFilter!(pred, MemberFunctionsTuple!(C, ""~names[0])) methods; 
     1552            alias enumerateOverloadsImpl!(C, pred, names[1 .. $]).result next; 
     1553 
     1554            static if (methods.length > 0) 
     1555                alias TypeTuple!(OverloadSet!(""~names[0], methods), next) result; 
     1556            else 
     1557                alias next result; 
     1558        } 
     1559        else 
     1560            alias TypeTuple!() result; 
     1561    } 
     1562 
     1563 
     1564    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1565    // Target functions 
     1566    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1567 
     1568    // Add a non-final check to the cherrypickMethod. 
     1569    template canonicalPicker(fun.../+[BUG 4217]+/) 
     1570    { 
     1571        enum bool canonicalPicker = !__traits(isFinalFunction, fun[0]) && 
     1572                                    cherrypickMethod!(fun); 
     1573    } 
     1574 
     1575    /* 
     1576     * A tuple of overload sets, each item of which consists of functions to be 
     1577     * implemented by the generated code. 
     1578     */ 
     1579    alias enumerateOverloads!(Base, canonicalPicker) targetOverloadSets; 
     1580 
     1581    /* 
     1582     * A tuple of the super class' constructors.  Used for forwarding 
     1583     * constructor calls. 
     1584     */ 
     1585    static if (__traits(hasMember, Base, "__ctor")) 
     1586        alias OverloadSet!("__ctor", __traits(getOverloads, Base, "__ctor")) 
     1587                ctorOverloadSet; 
     1588    else 
     1589        alias OverloadSet!("__ctor") ctorOverloadSet; // empty 
     1590 
     1591 
     1592    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1593    // Type information 
     1594    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1595 
     1596    /* 
     1597     * The generated code will be mixed into AutoImplement, which will be 
     1598     * instantiated in this module's scope.  Thus, any user-defined types are 
     1599     * out of scope and cannot be used directly (i.e. by their names). 
     1600     * 
     1601     * We will use FuncInfo instances for accessing return types and parameter 
     1602     * types of the implemented functions.  The instances will be populated to 
     1603     * the AutoImplement's scope in a certain way; see the populate() below. 
     1604     */ 
     1605 
     1606    // Returns the preferred identifier for the FuncInfo instance for the i-th 
     1607    // overloaded function with the name. 
     1608    template INTERNAL_FUNCINFO_ID(string name, size_t i) 
     1609    { 
     1610        enum string INTERNAL_FUNCINFO_ID = "F_" ~ name ~ "_" ~ toStringNow!(i); 
     1611    } 
     1612 
     1613    /* 
     1614     * Insert FuncInfo instances about all the target functions here.  This 
     1615     * enables the generated code to access type information via, for example, 
     1616     * "autoImplement_helper_.F_foo_1". 
     1617     */ 
     1618    template populate(overloads...) 
     1619    { 
     1620        static if (overloads.length > 0) 
     1621        { 
     1622            mixin populate!(overloads[0].name, overloads[0].contents); 
     1623            mixin populate!(overloads[1 .. $]); 
     1624        } 
     1625    } 
     1626    template populate(string name, methods...) 
     1627    { 
     1628        static if (methods.length > 0) 
     1629        { 
     1630            mixin populate!(name, methods[0 .. $ - 1]); 
     1631            // 
     1632            alias methods[$ - 1] target; 
     1633            enum ith = methods.length - 1; 
     1634            mixin( "alias FuncInfo!(target) " ~ 
     1635                        INTERNAL_FUNCINFO_ID!(name, ith) ~ ";" ); 
     1636        } 
     1637    } 
     1638 
     1639    public mixin populate!(targetOverloadSets); 
     1640    public mixin populate!(  ctorOverloadSet ); 
     1641 
     1642 
     1643    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1644    // Code-generating policies 
     1645    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1646 
     1647    /* Common policy configurations for generating constructors and methods. */ 
     1648    template CommonGeneratingPolicy() 
     1649    { 
     1650        // base class identifier which generated code should use 
     1651        enum string BASE_CLASS_ID = baseName; 
     1652 
     1653        // FuncInfo instance identifier which generated code should use 
     1654        template FUNCINFO_ID(string name, size_t i) 
     1655        { 
     1656            enum string FUNCINFO_ID = 
     1657                myName ~ "." ~ INTERNAL_FUNCINFO_ID!(name, i); 
     1658        } 
     1659 
     1660        // preferred identifier for i-th parameter variable 
     1661        template PARAMETER_VARIABLE_ID(size_t i) 
     1662        { 
     1663            enum string PARAMETER_VARIABLE_ID = "a" ~ toStringNow!(i); 
     1664        } 
     1665    } 
     1666 
     1667    /* Policy configurations for generating constructors. */ 
     1668    template ConstructorGeneratingPolicy() 
     1669    { 
     1670        mixin CommonGeneratingPolicy; 
     1671 
     1672        /* Generates constructor body.  Just forward to the base class' one. */ 
     1673        string generateFunctionBody(ctor.../+[BUG 4217]+/)() @property 
     1674        { 
     1675            enum varstyle = variadicFunctionStyle!(typeof(&ctor[0])); 
     1676 
     1677            static if (varstyle & (Variadic.C | Variadic.D)) 
     1678            { 
     1679                // the argptr-forwarding problem 
     1680                pragma(msg, "Warning: AutoImplement!(", Base, ") ", 
     1681                        "ignored variadic arguments to the constructor ", 
     1682                        FunctionTypeOf!(typeof(&ctor[0])) ); 
     1683            } 
     1684            return "super(args);"; 
     1685        } 
     1686    } 
     1687 
     1688    /* Policy configurations for genearting target methods. */ 
     1689    template MethodGeneratingPolicy() 
     1690    { 
     1691        mixin CommonGeneratingPolicy; 
     1692 
     1693        /* Geneartes method body. */ 
     1694        string generateFunctionBody(func.../+[BUG 4217]+/)() @property 
     1695        { 
     1696            return generateMethodBody!(Base, func); // given 
     1697        } 
     1698    } 
     1699 
     1700 
     1701    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1702    // Generated code 
     1703    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1704 
     1705    alias MemberFunctionGenerator!( ConstructorGeneratingPolicy!() ) 
     1706            ConstructorGenerator; 
     1707    alias MemberFunctionGenerator!( MethodGeneratingPolicy!() ) 
     1708            MethodGenerator; 
     1709 
     1710    public enum string code = 
     1711        ConstructorGenerator.generateCode!(  ctorOverloadSet ) ~ "\n" ~ 
     1712             MethodGenerator.generateCode!(targetOverloadSets); 
     1713 
     1714    debug (SHOW_GENERATED_CODE) 
     1715    { 
     1716        pragma(msg, "-------------------- < ", Base, " >"); 
     1717        pragma(msg, code); 
     1718        pragma(msg, "--------------------"); 
     1719    } 
     1720} 
     1721 
     1722//debug = SHOW_GENERATED_CODE; 
     1723unittest 
     1724{ 
     1725    // no function to implement 
     1726    { 
     1727        interface I_1 {} 
     1728        auto o = new AutoImplement!I_1; 
     1729    } 
     1730    // return value 
     1731    { 
     1732        interface I_2 { real test(); } 
     1733        auto o = new AutoImplement!I_2; 
     1734        assert(o.test() !<>= 0); // NaN 
     1735    } 
     1736    // parameters 
     1737    { 
     1738        interface I_3 { void test(int, in int, out int, ref int, lazy int); } 
     1739        auto o = new AutoImplement!I_3; 
     1740    } 
     1741    // use of user-defined type 
     1742    { 
     1743        typedef int MyInt; 
     1744        interface I_4 { MyInt test(); } 
     1745        auto o = new AutoImplement!I_4; 
     1746    } 
     1747    // overloads 
     1748    { 
     1749        interface I_5 
     1750        { 
     1751            void test(string); 
     1752            real test(real); 
     1753            int  test(); 
     1754            int  test() @property; // ? 
     1755        } 
     1756        auto o = new AutoImplement!I_5; 
     1757    } 
     1758    // constructor forwarding 
     1759    { 
     1760        static class C_6 
     1761        { 
     1762            this(int n) { assert(n == 42); } 
     1763            this(string s) { assert(s == "Deeee"); } 
     1764            this(...) {} 
     1765        } 
     1766        auto o1 = new AutoImplement!C_6(42); 
     1767        auto o2 = new AutoImplement!C_6("Deeee"); 
     1768        auto o3 = new AutoImplement!C_6(1, 2, 3, 4); 
     1769    } 
     1770    /+ // deep inheritance 
     1771    { 
     1772    // XXX [BUG 2525,3525] 
     1773    // NOTE: [r494] func.c(504-571) FuncDeclaration::semantic() 
     1774        interface I { void foo(); } 
     1775        interface J : I {} 
     1776        interface K : J {} 
     1777        static abstract class C_8 : K {} 
     1778        auto o = new AutoImplement!C_8; 
     1779    } +/ 
     1780    // doc example 
     1781    { 
     1782        static class Base 
     1783        { 
     1784            int m_value; 
     1785            this(int v) { m_value = v; } 
     1786            int value() @property { return m_value; } 
     1787 
     1788            abstract real realValue() @property; 
     1789            abstract void doSomething(); 
     1790        } 
     1791 
     1792        auto obj = new AutoImplement!Base(42); 
     1793        assert(obj.value == 42); 
     1794 
     1795        assert(obj.realValue !<>= 0); // NaN 
     1796        obj.doSomething(); 
     1797    } 
     1798} 
     1799 
     1800 
     1801/** 
     1802The default $(EM how)-policy for $(D AutoImplement).  Every generated function 
     1803returns the default value without doing anything. 
     1804 */ 
     1805template generateEmptyFunction(C, func.../+[BUG 4217]+/) 
     1806{ 
     1807    static if (is(ReturnType!(func) == void)) 
     1808        enum string generateEmptyFunction = q{ 
     1809        }; 
     1810    else static if (functionAttributes!(func) & FunctionAttribute.REF) 
     1811        enum string generateEmptyFunction = q{ 
     1812            static typeof(return) dummy; 
     1813            return dummy; 
     1814        }; 
     1815    else 
     1816        enum string generateEmptyFunction = q{ 
     1817            return typeof(return).init; 
     1818        }; 
     1819} 
     1820 
     1821 
     1822/** 
     1823A $(EM how)-policy for $(D AutoImplement).  Every generated function fails with 
     1824$(D AssertError) and does never return.  Useful for trapping use of 
     1825not-yet-implemented functions. 
     1826 
     1827Example: 
     1828-------------------- 
     1829class C 
     1830{ 
     1831    abstract void notYetImplemented(); 
     1832} 
     1833 
     1834void main() 
     1835{ 
     1836    auto obj = new AutoImplement!(C, generateAssertTrap); 
     1837    obj.notYetImplemented(); // throws AssertError 
     1838} 
     1839-------------------- 
     1840 */ 
     1841template generateAssertTrap(C, func.../+[BUG 4217]+/) 
     1842{ 
     1843    enum string generateAssertTrap = 
     1844        `assert(0, "` ~ (C.stringof ~ "." ~ __traits(identifier, func)) 
     1845                ~ ` is not implemented");`; 
     1846} 
     1847 
     1848unittest // doc example 
     1849{ 
     1850    static class C 
     1851    { 
     1852        abstract void notYetImplemented(); 
     1853    } 
     1854 
     1855    auto o = new AutoImplement!(C, generateAssertTrap); 
     1856    try 
     1857    { 
     1858        o.notYetImplemented(); 
     1859        assert(0); 
     1860    } 
     1861    catch (Error e) {} 
     1862} 
     1863 
     1864 
     1865/* 
     1866Used by MemberFunctionGenerator. 
     1867 */ 
     1868private template OverloadSet(string nam, T...) 
     1869{ 
     1870    enum string name = nam; 
     1871    alias T contents; 
     1872} 
     1873 
     1874/* 
     1875Used by MemberFunctionGenerator. 
     1876 */ 
     1877private template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func)) 
     1878{ 
     1879    alias         ReturnType!(T) RT; 
     1880    alias ParameterTypeTuple!(T) PT; 
     1881} 
     1882 
     1883/* 
     1884General-purpose member function generator. 
     1885 */ 
     1886private template MemberFunctionGenerator(alias Policy) 
     1887{ 
     1888private static: 
     1889    //mixin Policy; // can't 
     1890 
     1891    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1892    // Internal stuffs 
     1893    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1894 
     1895    enum CONSTRUCTOR_NAME = "__ctor"; 
     1896    enum WITH_BASE_CLASS  = __traits(compiles, Policy.BASE_CLASS_ID); 
     1897 
     1898    // Returns a tuple consisting of 0,1,2,...,n-1.  For static foreach. 
     1899    template CountUp(size_t n) 
     1900    { 
     1901        static if (n > 0) 
     1902            alias TypeTuple!(CountUp!(n - 1), n - 1) CountUp; 
     1903        else 
     1904            alias TypeTuple!() CountUp; 
     1905    } 
     1906 
     1907 
     1908    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1909    // Code generator 
     1910    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1911 
     1912    /* 
     1913     * Runs through all the target overload sets and generates D code which 
     1914     * implements all the functions in the overload sets. 
     1915     */ 
     1916    public string generateCode(overloads...)() @property 
     1917    { 
     1918        string code = ""; 
     1919 
     1920        // run through all the overload sets 
     1921        foreach (i_; CountUp!(0 + overloads.length)) // workaround 
     1922        { 
     1923            enum i = 0 + i_; // workaround 
     1924            alias overloads[i] oset; 
     1925 
     1926            code ~= generateCodeForOverloadSet!(oset); 
     1927 
     1928            static if (WITH_BASE_CLASS && oset.name != CONSTRUCTOR_NAME) 
     1929            { 
     1930                // The generated function declarations may hide existing ones 
     1931                // in the base class (cf. HiddenFuncError), so we put an alias 
     1932                // declaration here to reveal possible hidden functions. 
     1933                code ~= Format!("alias %s.%s %s;\n", 
     1934                            Policy.BASE_CLASS_ID, // [BUG 2540] super. 
     1935                            oset.name, oset.name ); 
     1936            } 
     1937        } 
     1938        return code; 
     1939    } 
     1940 
     1941    // handle each overload set 
     1942    private string generateCodeForOverloadSet(alias oset)() @property 
     1943    { 
     1944        string code = ""; 
     1945 
     1946        foreach (i_; CountUp!(0 + oset.contents.length)) // workaround 
     1947        { 
     1948            enum i = 0 + i_; // workaround 
     1949            code ~= generateFunction!( 
     1950                    oset.contents[i], Policy.FUNCINFO_ID!(oset.name, i)) ~ "\n"; 
     1951        } 
     1952        return code; 
     1953    } 
     1954 
     1955    /* 
     1956     * Returns D code which implements the function func.  This function 
     1957     * actually generates only the declarator part; the function body part is 
     1958     * generated by the functionGenerator() policy. 
     1959     */ 
     1960    //private string generateFunction(alias func, string myFuncInfo)() @property 
     1961    private string generateFunction(args_.../+[BUG 4217]+/)() @property 
     1962    { 
     1963        alias args_[0..1] func; enum myFuncInfo = args_[1]; 
     1964 
     1965        enum name   = __traits(identifier, func); 
     1966        enum isCtor = (name == CONSTRUCTOR_NAME); 
     1967 
     1968        string code; // the result 
     1969 
     1970        /*** Function Declarator ***/ 
     1971        { 
     1972            alias FunctionAttribute FA; 
     1973            enum atts     = functionAttributes!(func); 
     1974            enum realName = isCtor ? "this" : name; 
     1975 
     1976            /* Just for the sake of Format!(...). */ 
     1977            static string make_postAtts() 
     1978            { 
     1979                string poatts = ""; 
     1980                if (atts & FA.PURE    ) poatts ~= " pure"; 
     1981                if (atts & FA.NOTHROW ) poatts ~= " nothrow"; 
     1982                if (atts & FA.PROPERTY) poatts ~= " @property"; 
     1983                if (atts & FA.SAFE    ) poatts ~= " @safe"; 
     1984                if (atts & FA.TRUSTED ) poatts ~= " @trusted"; 
     1985                return poatts; 
     1986            } 
     1987            enum postAtts = make_postAtts(); 
     1988 
     1989            static string make_returnType() 
     1990            { 
     1991                string rtype = ""; 
     1992 
     1993                if (!isCtor) 
     1994                { 
     1995                    if (atts & FA.REF) rtype ~= "ret "; 
     1996                    rtype ~= myFuncInfo ~ ".RT"; 
     1997                } 
     1998                return rtype; 
     1999            } 
     2000            enum returnType = make_returnType(); 
     2001 
     2002            // 
     2003            code ~= Format!("extern(%s) %s %s(%s) %s\n", 
     2004                    functionLinkage!(func), 
     2005                    returnType, 
     2006                    realName, 
     2007                    ""~generateParameters!(func, myFuncInfo), 
     2008                    postAtts ); 
     2009        } 
     2010 
     2011        /*** Function Body ***/ 
     2012        code ~= "{\n"; 
     2013        { 
     2014            enum nparams = ParameterTypeTuple!(func).length; 
     2015 
     2016            /* Declare keywords: args, self and parent. */ 
     2017            string preamble; 
     2018 
     2019            preamble ~= "alias TypeTuple!(" ~ enumerateParameters!(nparams) ~ ") args;\n"; 
     2020            if (!isCtor) 
     2021            { 
     2022                preamble ~= "alias " ~ name ~ " self;\n"; 
     2023                if (WITH_BASE_CLASS && !__traits(isAbstractFunction, func)) 
     2024                    //preamble ~= "alias super." ~ name ~ " parent;\n"; // [BUG 2540] 
     2025                    preamble ~= "auto parent = &super." ~ name ~ ";\n"; 
     2026            } 
     2027 
     2028            // 
     2029            code ~= preamble; 
     2030            code ~= Policy.generateFunctionBody!(func); 
     2031        } 
     2032        code ~= "}"; 
     2033 
     2034        return code; 
     2035    } 
     2036 
     2037    /* 
     2038     * Returns D code which declares function parameters. 
     2039     * "ref int a0, real a1, ..." 
     2040     */ 
     2041    //private string generateParameters(alias func, string myFuncInfo)() @property 
     2042    private string generateParameters(args_.../+[BUG 4217]+/)() @property 
     2043    { 
     2044        alias args_[0..1] func; enum myFuncInfo = args_[1]; 
     2045 
     2046        alias ParameterStorageClass STC; 
     2047        alias ParameterStorageClassTuple!(func) stcs; 
     2048        enum nparams = stcs.length; 
     2049 
     2050        string params = ""; // the result 
     2051 
     2052        foreach (i, stc; stcs) 
     2053        { 
     2054            if (i > 0) params ~= ", "; 
     2055 
     2056            // Parameter storage classes. 
     2057            if (stc & STC.SCOPE) params ~= "scope "; 
     2058            if (stc & STC.OUT  ) params ~= "out "; 
     2059            if (stc & STC.REF  ) params ~= "ref "; 
     2060            if (stc & STC.LAZY ) params ~= "lazy "; 
     2061 
     2062            // Take parameter type from the FuncInfo. 
     2063            params ~= myFuncInfo ~ ".PT[" ~ toStringNow!(i) ~ "]"; 
     2064 
     2065            // Declare a parameter variable. 
     2066            params ~= " " ~ Policy.PARAMETER_VARIABLE_ID!(i); 
     2067        } 
     2068 
     2069        // Add some ellipsis part if needed. 
     2070        final switch (variadicFunctionStyle!(func)) 
     2071        { 
     2072            case Variadic.NO: 
     2073                break; 
     2074 
     2075            case Variadic.C, Variadic.D: 
     2076                // (...) or (a, b, ...) 
     2077                params ~= (nparams == 0) ? "..." : ", ..."; 
     2078                break; 
     2079 
     2080            case Variadic.TYPESAFE: 
     2081                params ~= " ..."; 
     2082                break; 
     2083        } 
     2084 
     2085        return params; 
     2086    } 
     2087 
     2088    // Returns D code which enumerates n parameter variables using comma as the 
     2089    // separator.  "a0, a1, a2, a3" 
     2090    private string enumerateParameters(size_t n)() @property 
     2091    { 
     2092        string params = ""; 
     2093 
     2094        foreach (i_; CountUp!(n)) 
     2095        { 
     2096            enum i = 0 + i_; // workaround 
     2097            if (i > 0) params ~= ", "; 
     2098            params ~= Policy.PARAMETER_VARIABLE_ID!(i); 
     2099        } 
     2100        return params; 
     2101    } 
     2102}