Function overloading
Vladimir
v.voinkov at gmail.com
Tue Jul 31 05:44:41 PDT 2007
Regan Heath Wrote:
> Vladimir wrote:
> > Ok, it works for that case.
> >
> > I'm playing with string template parameters. It's a kind of miracle
> > for me, a c++ programmer. I made a precompiled wildcard match and
> > would like static version to overload as follows:
> >
> > bool wildcardMatch (T : char[]) (T wild, T str) // general case {
> > return false; }
> >
> > bool wildcardMatch (char[] W) (T str) // static case { return false;
> > }
> >
> > void main() { wildcardMatch ("*", "123"); wildcardMatch !("*")
> > ("123"); }
> >
> > Is that posible?
>
> At first I thought, maybe "static if" would be better than a template
> specialization, i.e.
>
> bool wildcardMatch (T : char[]) (T wild, T str)
> {
> static if (wild == "*") return true;
> return false;
> }
>
> but of course the value of 'wild' is not known at compile time... or is it?
>
> If it's a constant as in your example 'main' above then it is and the
> compiler could theoretically evaluate it.
>
> But then I thought, if you know it's "*" why make a call to
> wildcardMatch at all? (after all it will always match)
>
> I came up with:
>
> bool someOtherTpl (T : char[]) (T wild, T str, bool something)
> {
> if (something)
> wildcardMatch(wild, str);
> }
>
> someOtherTpl("*", ...
>
> which is a case where you have to code the call to wildcardMatch because
> you don't know wild was "*" at that point.
>
>
> The closest I managed to get with template specialization is:
>
> import std.stdio;
>
> bool wildcardMatch (T) (T wild, T str) // general case
> {
> writefln("general case");
> return false;
> }
>
> bool wildcardMatch (W:invariant(char[1]), S) (W wild, S str) // "*" case
> {
> writefln("* case");
> return false;
> }
>
> void main()
> {
> wildcardMatch!(char[])("*asd*".dup, "123".dup);
> wildcardMatch!(invariant(char[1]),char[])("*", "123".dup);
> wildcardMatch!(invariant(char[1]),char[])("a", "123".dup);
> }
>
> Which incorrectly calls the * case for the wild string "a" because of
> course it is specializing using a static array of 1 character.
>
> Regan
import std.string;
bool wildcardMatch (char[] E) (char[] aString)
{
return Expression !(E).Result.match (aString);
}
private
{
const int TypeEmpty = 0;
const int TypeAsterisk = 1;
const int TypeQuestion = 2;
const int TypeChar = 3;
//
int expressionType (char[] aExpression)
{
if (aExpression.length == 0)
return TypeEmpty;
if (aExpression [0] == '*')
return TypeAsterisk;
if (aExpression [0] == '?')
return TypeQuestion;
return TypeChar;
}
//
char[] headExpression (char[] aExpression)
{
return aExpression [0 .. length - tailExpression (aExpression).length];
}
//
char[] tailExpression (char[] aExpression)
{
int type = TypeEmpty;
for (int i = 0; i < aExpression.length; ++i)
{
if (i == 0)
{
switch (aExpression [i])
{
case '*':
type = TypeAsterisk;
break;
case '?':
type = TypeQuestion;
break;
default:
type = TypeChar;
}
}
else if (type == TypeAsterisk)
{
if (aExpression [i] != '*')
return aExpression [i .. length];
}
else if (type == TypeQuestion)
{
if (aExpression [i] != '?')
return aExpression [i .. length];
}
else
{
if (aExpression [i] == '*' || aExpression [i] == '?')
return aExpression [i .. length];
}
}
return "";
}
template Expression (char[] E)
{
static if (expressionType (E) == TypeAsterisk)
alias AsteriksMatch !(E) Result;
else static if (expressionType (E) == TypeQuestion)
alias QuestionMatch !(E) Result;
else static if (expressionType (E) == TypeChar)
alias CharMatch !(E) Result;
else
alias EmptyMatch !(E) Result;
}
template AsteriksMatch (char[] E)
{
static assert (expressionType (E) == TypeAsterisk);
bool match (char[] aString)
{
const char[] Tail = tailExpression (E);
static if (Tail.length == 0)
return true;
for (int i = aString.length; i >= 0; --i)
{
if (Expression !(Tail).Result.match (aString [i .. length]))
return true;
}
return false;
}
}
template QuestionMatch (char[] E)
{
static assert (expressionType (E) == TypeQuestion);
bool match (char[] aString)
{
const char[] Head = headExpression (E);
if (aString.length == Head.length)
return true;
if (aString.length < Head.length)
return false;
const char[] Tail = tailExpression (E);
return Expression !(Tail).Result.match (aString [Head.length .. length]);
}
}
template CharMatch (char[] E)
{
static assert (expressionType (E) == TypeChar);
bool match (char[] aString)
{
const char[] Head = headExpression (E);
if (aString.length < Head.length)
return false;
if (icmp (Head, aString [0 .. Head.length]) != 0)
return false;
const char[] Tail = tailExpression (E);
return Expression !(Tail).Result.match (aString [Head.length .. length]);
}
}
template EmptyMatch (char[] E)
{
static assert (expressionType (E) == TypeEmpty);
bool match (char[] aString)
{
return aString.length == 0;
}
}
}
It can be used with any expresion known at compile time:
char[] checkme = "123456";
wildcardMatch !("???5*") (checkme);
wildcardMatch !("1???5*") (checkme);
wildcardMatch !("?????????5*") (checkme);
I dont know how it could be useful, it's just a toy. Surprisingly, I can't freely overload functions like in C++
More information about the Digitalmars-d-learn
mailing list