Thread overview
Different class template args to generate same template instance?
Nov 02, 2009
Nick Sabalausky
Nov 02, 2009
BCS
Nov 02, 2009
Nick Sabalausky
Nov 02, 2009
downs
Nov 02, 2009
Nick Sabalausky
Nov 02, 2009
Nick Sabalausky
November 02, 2009
I'd like to have a sub-class that's templated on a potentially-duplicated name and an optional disambiguating type. To illustrate:

class Foo
{
}

/*
Three possible names/types are:
- sam, human
- zoe, human
- zoe, starship
*/
class SubFoo(char[] name, char[] type)
{
    static if(name == "sam" && type == "human")
        // create members specific to the only sam
    else static if(name == "zoe" && type == "human")
        // create members specific to the human zoe
    static if(name == "zoe" && type == "starship")
        // create members specific to the starship zoe
    else
        static assert(false, "Invalid name/type");
}

But unlike in that example, *most* of the names will only exist as one possible type and will therefore be completely unambiguous just by themselves. So, I would really like to be able to make the type optional and just have a "static assert(false)" for any use of an ambiguous name that isn't disambiguated by a type. Kind of like this:

class SubFoo(char[] name, char[] type="")
{
    static if(name == "sam" && (type == "human" || type==""))
        // create members specific to the only sam
    else static if(name == "zoe" && type == "human")
        // create members specific to the human zoe
    static if(name == "zoe" && type == "starship")
        // create members specific to the starship zoe
    static if(name == "zoe" && type == "")
        static assert(false, "zoe might be either the human or the starship,
please specify which one");
    else
        static assert(false, "Invalid name/type");
}

Problem is, that won't work because SubFoo!("sam") and SubFoo!("sam", "human") are treated as different types. So...is there any trickery I could do so that SubFoo!("sam") and SubFoo!("sam", "human") would resolve to the same subclass of Foo?

I don't think any solution involving merging the name/type fields into anything like "sam.human" would work because the valid names could be just about any sequence of chars (this source file will be generated by a tool) so any possible "disambiguated" string could potentially conflict with a plain non-disambiguated name. Names being any sequence of chars also rules out anything like "class SubFoo_sam_human : Foo", because name could be something like "++.  /&".


November 02, 2009
Hello Nick,


> So...is there any trickery I
> could do so that SubFoo!("sam") and SubFoo!("sam", "human") would
> resolve to the same subclass of Foo?

Make a SubFoo!(char[] s) that does your logic and if it passesa alises to SubFoo!(s,"")


November 02, 2009
"BCS" <none@anon.com> wrote in message news:a6268ffc3898cc29d1f554dfe2@news.digitalmars.com...
> Hello Nick,
>
>
>> So...is there any trickery I
>> could do so that SubFoo!("sam") and SubFoo!("sam", "human") would
>> resolve to the same subclass of Foo?
>
> Make a SubFoo!(char[] s) that does your logic and if it passesa alises to SubFoo!(s,"")
>
>

I'm not sure I understand...?


November 02, 2009
Nick Sabalausky wrote:
> "BCS" <none@anon.com> wrote in message news:a6268ffc3898cc29d1f554dfe2@news.digitalmars.com...
>> Hello Nick,
>>
>>
>>> So...is there any trickery I
>>> could do so that SubFoo!("sam") and SubFoo!("sam", "human") would
>>> resolve to the same subclass of Foo?
>> Make a SubFoo!(char[] s) that does your logic and if it passesa alises to SubFoo!(s,"")
>>
>>
> 
> I'm not sure I understand...?
> 
> 

I think what he's trying to say is

template SubFoo!(char[] name, char[] type) {
  static if (name == "sam" && (type == "human" || type == "")) alias _SubFoo!("sam", "human") SubFoo;
  /* etc */
}
November 02, 2009
"downs" <default_357-line@yahoo.de> wrote in message news:hcnjit$4na$1@digitalmars.com...
> Nick Sabalausky wrote:
>> "BCS" <none@anon.com> wrote in message news:a6268ffc3898cc29d1f554dfe2@news.digitalmars.com...
>>> Hello Nick,
>>>
>>>
>>>> So...is there any trickery I
>>>> could do so that SubFoo!("sam") and SubFoo!("sam", "human") would
>>>> resolve to the same subclass of Foo?
>>> Make a SubFoo!(char[] s) that does your logic and if it passesa alises
>>> to
>>> SubFoo!(s,"")
>>>
>>>
>>
>> I'm not sure I understand...?
>>
>>
>
> I think what he's trying to say is
>
> template SubFoo!(char[] name, char[] type) {
>  static if (name == "sam" && (type == "human" || type == "")) alias
> _SubFoo!("sam", "human") SubFoo;
>  /* etc */
> }

Ahh! Thanks all, that works perfectly:

-------------------------------------------------------------
module foo;

class Foo
{
    protected char[] _n="Plain Foo";
    char[] n()
    {
        return _n.dup;
    }
}

template SubFoo(char[] name, char[] type="")
{
    static if (name == "sam" && (type == "human" || type == ""))
        alias _SubFoo!(name, "human") SubFoo;
    else static if(
        (name == "zoe" && type == "human") ||
        (name == "zoe" && type == "starship")
    )
        alias _SubFoo!(name, type) SubFoo;
    else static if(name == "zoe" && type == "")
        static assert(false, "Name '"~name~"' is ambiguous");
    else
        static assert(false, "Invalid name/type: '"~name~"' '"~type~"'");
}

private class _SubFoo(char[] name, char[] type) : Foo
{
    static if(name == "sam" && type == "human")
        this() { _n = "sam human"; }
    else static if(name == "zoe" && type == "human")
        this() { _n = "zoe human"; }
    else static if(name == "zoe" && type == "starship")
        this() { _n = "zoe starship"; }
    else
        static assert(false, "Invalid name/type: '"~name~"' '"~type~"'");
}
-------------------------------------------------------------
module main;
import tango.io.Stdout;
import foo;

void main()
{
    auto f  = new Foo();
    auto s_ = new SubFoo!("sam");
    auto sh = new SubFoo!("sam", "human");
    auto zh = new SubFoo!("zoe", "human");
    auto zs = new SubFoo!("zoe", "starship");

    // ERROR: Name 'zoe' is ambiguous
    //auto z_ = new SubFoo!("zoe");

    // ERROR: Invalid name/type 'dummy' 'dude'
    //auto d_ = new SubFoo!("dummy", "dude");

    Stdout.formatln("f : {}", f.n);  // OUT: f : Plain Foo
    Stdout.formatln("s_: {}", s_.n); // OUT: s_: sam human
    Stdout.formatln("sh: {}", sh.n); // OUT: sh: sam human
    Stdout.formatln("zh: {}", zh.n); // OUT: zh: zoe human
    Stdout.formatln("zs: {}", zs.n); // OUT: zs: zoe starship
}
-------------------------------------------------------------



November 02, 2009
"Nick Sabalausky" <a@a.a> wrote in message news:hcnlh7$msb$1@digitalmars.com...
> "downs" <default_357-line@yahoo.de> wrote in message news:hcnjit$4na$1@digitalmars.com...
>> Nick Sabalausky wrote:
>>> "BCS" <none@anon.com> wrote in message news:a6268ffc3898cc29d1f554dfe2@news.digitalmars.com...
>>>> Hello Nick,
>>>>
>>>>
>>>>> So...is there any trickery I
>>>>> could do so that SubFoo!("sam") and SubFoo!("sam", "human") would
>>>>> resolve to the same subclass of Foo?
>>>> Make a SubFoo!(char[] s) that does your logic and if it passesa alises
>>>> to
>>>> SubFoo!(s,"")
>>>>
>>>>
>>>
>>> I'm not sure I understand...?
>>>
>>>
>>
>> I think what he's trying to say is
>>
>> template SubFoo!(char[] name, char[] type) {
>>  static if (name == "sam" && (type == "human" || type == "")) alias
>> _SubFoo!("sam", "human") SubFoo;
>>  /* etc */
>> }
>
> Ahh! Thanks all, that works perfectly:
>
> -------------------------------------------------------------
> module foo;
>
> class Foo
> {
>    protected char[] _n="Plain Foo";
>    char[] n()
>    {
>        return _n.dup;
>    }
> }
>
> template SubFoo(char[] name, char[] type="")
> {
>    static if (name == "sam" && (type == "human" || type == ""))
>        alias _SubFoo!(name, "human") SubFoo;
>    else static if(
>        (name == "zoe" && type == "human") ||
>        (name == "zoe" && type == "starship")
>    )
>        alias _SubFoo!(name, type) SubFoo;
>    else static if(name == "zoe" && type == "")
>        static assert(false, "Name '"~name~"' is ambiguous");
>    else
>        static assert(false, "Invalid name/type: '"~name~"' '"~type~"'");
> }
>
> private class _SubFoo(char[] name, char[] type) : Foo
> {
>    static if(name == "sam" && type == "human")
>        this() { _n = "sam human"; }
>    else static if(name == "zoe" && type == "human")
>        this() { _n = "zoe human"; }
>    else static if(name == "zoe" && type == "starship")
>        this() { _n = "zoe starship"; }
>    else
>        static assert(false, "Invalid name/type: '"~name~"' '"~type~"'");
> }
> -------------------------------------------------------------
> module main;
> import tango.io.Stdout;
> import foo;
>
> void main()
> {
>    auto f  = new Foo();
>    auto s_ = new SubFoo!("sam");
>    auto sh = new SubFoo!("sam", "human");
>    auto zh = new SubFoo!("zoe", "human");
>    auto zs = new SubFoo!("zoe", "starship");
>
>    // ERROR: Name 'zoe' is ambiguous
>    //auto z_ = new SubFoo!("zoe");
>
>    // ERROR: Invalid name/type 'dummy' 'dude'
>    //auto d_ = new SubFoo!("dummy", "dude");
>
>    Stdout.formatln("f : {}", f.n);  // OUT: f : Plain Foo
>    Stdout.formatln("s_: {}", s_.n); // OUT: s_: sam human
>    Stdout.formatln("sh: {}", sh.n); // OUT: sh: sam human
>    Stdout.formatln("zh: {}", zh.n); // OUT: zh: zoe human
>    Stdout.formatln("zs: {}", zs.n); // OUT: zs: zoe starship
> }
> -------------------------------------------------------------
>

Oops, just realized that main doesn't necessarily prove that the SubFoo!("sam") and SubFoo!("sam", "human") are the same types. But this passes fine, so all looks ok, thanks again! :

static assert(is( SubFoo!("sam") == SubFoo!("sam", "human") ));