mirror of
https://github.com/dlang/phobos.git
synced 2025-05-04 09:00:22 +03:00
Merge pull request #544 from 9rnsr/fix7878
Issue 7878 - A problem with purity and general templated algorithms
This commit is contained in:
commit
8e37bf3d01
2 changed files with 11 additions and 105 deletions
|
@ -6977,7 +6977,8 @@ sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable,
|
||||||
Range)(Range r)
|
Range)(Range r)
|
||||||
{
|
{
|
||||||
alias binaryFun!(less) lessFun;
|
alias binaryFun!(less) lessFun;
|
||||||
static if (is(typeof(lessFun(r.front, r.front)) == bool))
|
alias typeof(lessFun(r.front, r.front)) LessRet; // instantiate lessFun
|
||||||
|
static if (is(LessRet == bool))
|
||||||
{
|
{
|
||||||
sortImpl!(lessFun, ss)(r);
|
sortImpl!(lessFun, ss)(r);
|
||||||
static if(is(typeof(text(r))))
|
static if(is(typeof(text(r))))
|
||||||
|
|
113
std/functional.d
113
std/functional.d
|
@ -40,57 +40,21 @@ template unaryFun(alias fun, bool byRef = false, string parmName = "a")
|
||||||
{
|
{
|
||||||
static if (is(typeof(fun) : string))
|
static if (is(typeof(fun) : string))
|
||||||
{
|
{
|
||||||
template Body(ElementType)
|
|
||||||
{
|
|
||||||
// enum testAsExpression = "{"~ElementType.stringof
|
|
||||||
// ~" "~parmName~"; return ("~fun~");}()";
|
|
||||||
enum testAsExpression = "{ ElementType "~parmName
|
|
||||||
~"; return ("~fun~");}()";
|
|
||||||
enum testAsStmts = "{"~ElementType.stringof
|
|
||||||
~" "~parmName~"; "~fun~"}()";
|
|
||||||
// pragma(msg, "Expr: "~testAsExpression);
|
|
||||||
// pragma(msg, "Stmts: "~testAsStmts);
|
|
||||||
static if (__traits(compiles, mixin(testAsExpression)))
|
|
||||||
{
|
|
||||||
enum string code = "return (" ~ fun ~ ");";
|
|
||||||
alias typeof(mixin(testAsExpression)) ReturnType;
|
|
||||||
}
|
|
||||||
// else static if (__traits(compiles, mixin(testAsStmts)))
|
|
||||||
// {
|
|
||||||
// enum string code = fun;
|
|
||||||
// alias typeof(mixin(testAsStmts)) ReturnType;
|
|
||||||
// }
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Credit for this idea goes to Don Clugston
|
|
||||||
// static assert is a bit broken,
|
|
||||||
// better to do it this way to provide a backtrace.
|
|
||||||
// pragma(msg, "Bad unary function: " ~ fun ~ " for type "
|
|
||||||
// ~ ElementType.stringof);
|
|
||||||
static assert(false, "Bad unary function: " ~ fun ~
|
|
||||||
" for type " ~ ElementType.stringof);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static if (byRef)
|
static if (byRef)
|
||||||
{
|
{
|
||||||
Body!(ElementType).ReturnType unaryFun(ElementType)(ref ElementType __a)
|
auto unaryFun(ElementType)(ref ElementType __a)
|
||||||
{
|
{
|
||||||
mixin("alias __a "~parmName~";");
|
mixin("alias __a "~parmName~";");
|
||||||
mixin(Body!(ElementType).code);
|
mixin("return (" ~ fun ~ ");");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Body!(ElementType).ReturnType unaryFun(ElementType)(ElementType __a)
|
auto unaryFun(ElementType)(ElementType __a)
|
||||||
{
|
{
|
||||||
mixin("alias __a "~parmName~";");
|
mixin("alias __a "~parmName~";");
|
||||||
mixin(Body!(ElementType).code);
|
mixin("return (" ~ fun ~ ");");
|
||||||
}
|
}
|
||||||
// string mixme = "Body!(ElementType).ReturnType"
|
|
||||||
// " unaryFun(ElementType)(ElementType a)
|
|
||||||
// { " ~ Body!(ElementType).code ~ " }";
|
|
||||||
// mixin(mixme);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -134,76 +98,18 @@ template binaryFun(alias fun, string parm1Name = "a",
|
||||||
{
|
{
|
||||||
static if (is(typeof(fun) : string))
|
static if (is(typeof(fun) : string))
|
||||||
{
|
{
|
||||||
template Body(ElementType1, ElementType2)
|
auto binaryFun(ElementType1, ElementType2)
|
||||||
{
|
|
||||||
enum testAsExpression = "{ ElementType1 "
|
|
||||||
~parm1Name~"; ElementType2 "
|
|
||||||
~parm2Name~"; return ("~fun~");}()";
|
|
||||||
// enum testAsExpression = "{"~ElementType1.stringof
|
|
||||||
// ~" "~parm1Name~"; "~ElementType2.stringof
|
|
||||||
// ~" "~parm2Name~"; return ("~fun~");}()";
|
|
||||||
// enum testAsStmts = "{"~ElementType1.stringof
|
|
||||||
// ~" "~parm1Name~"; "~ElementType2.stringof
|
|
||||||
// ~" "~parm2Name~"; "~fun~"}()";
|
|
||||||
static if (__traits(compiles, mixin(testAsExpression)))
|
|
||||||
{
|
|
||||||
enum string code = "return (" ~ fun ~ ");";
|
|
||||||
alias typeof(mixin(testAsExpression)) ReturnType;
|
|
||||||
}
|
|
||||||
// else static if (__traits(compiles, mixin(testAsStmts)))
|
|
||||||
// {
|
|
||||||
// enum string code = fun;
|
|
||||||
// alias typeof(mixin(testAsStmts)) ReturnType;
|
|
||||||
// }
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Credit for this idea goes to Don Clugston
|
|
||||||
enum string msg =
|
|
||||||
"Bad binary function q{" ~ fun ~ "}."
|
|
||||||
~" You need to use a valid D expression using symbols "
|
|
||||||
~parm1Name~" of type "~ElementType1.stringof~" and "
|
|
||||||
~parm2Name~" of type "~ElementType2.stringof~"."
|
|
||||||
~(fun.length && fun[$ - 1] == ';'
|
|
||||||
? " The trailing semicolon is _not_ needed."
|
|
||||||
: "")
|
|
||||||
~(fun.length && fun[$ - 1] == '}'
|
|
||||||
? " The trailing bracket is mistaken."
|
|
||||||
: "");
|
|
||||||
static assert(false, msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Body!(ElementType1, ElementType2).ReturnType
|
|
||||||
binaryFun(ElementType1, ElementType2)
|
|
||||||
(ElementType1 __a, ElementType2 __b)
|
(ElementType1 __a, ElementType2 __b)
|
||||||
{
|
{
|
||||||
mixin("alias __a "~parm1Name~";");
|
mixin("alias __a "~parm1Name~";");
|
||||||
mixin("alias __b "~parm2Name~";");
|
mixin("alias __b "~parm2Name~";");
|
||||||
mixin(Body!(ElementType1, ElementType2).code);
|
mixin("return (" ~ fun ~ ");");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alias fun binaryFun;
|
alias fun binaryFun;
|
||||||
}
|
}
|
||||||
// static if (is(typeof(comp) : string))
|
|
||||||
// {
|
|
||||||
// // @@@BUG1816@@@: typeof(mixin(comp)) should work
|
|
||||||
// typeof({
|
|
||||||
// static ElementType1 a;
|
|
||||||
// static ElementType2 b;
|
|
||||||
// return mixin(comp);
|
|
||||||
// }())
|
|
||||||
// binaryFun(ElementType1, ElementType2)
|
|
||||||
// (ElementType1 a, ElementType2 b)
|
|
||||||
// {
|
|
||||||
// return mixin(comp);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// alias comp binaryFun;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
|
@ -239,15 +145,14 @@ unittest
|
||||||
*/
|
*/
|
||||||
//alias binaryFun!(q{a == b}) equalTo;
|
//alias binaryFun!(q{a == b}) equalTo;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Binary predicate that reverses the order of arguments, e.g., given
|
Binary predicate that reverses the order of arguments, e.g., given
|
||||||
$(D pred(a, b)), returns $(D pred(b, a)).
|
$(D pred(a, b)), returns $(D pred(b, a)).
|
||||||
*/
|
*/
|
||||||
template binaryReverseArgs(alias pred)
|
template binaryReverseArgs(alias pred)
|
||||||
{
|
{
|
||||||
typeof({ ElementType1 a; ElementType2 b; return pred(b, a);}())
|
auto binaryReverseArgs(ElementType1, ElementType2)
|
||||||
binaryReverseArgs(ElementType1, ElementType2)(ElementType1 a,
|
(ElementType1 a, ElementType2 b)
|
||||||
ElementType2 b)
|
|
||||||
{
|
{
|
||||||
return pred(b, a);
|
return pred(b, a);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue