www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Different class template args to generate same template instance?

reply "Nick Sabalausky" <a a.a> writes:
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 "++.  /&".
Nov 02 2009
parent reply BCS <none anon.com> writes:
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,"")
Nov 02 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"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...?
Nov 02 2009
parent reply downs <default_357-line yahoo.de> writes:
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 */ }
Nov 02 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"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 } -------------------------------------------------------------
Nov 02 2009
parent "Nick Sabalausky" <a a.a> writes:
"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") ));
Nov 02 2009