D-Programming-Language/phobos — pull request #937 by denis-sh (2012-11-12 14:47:09+00:00)
Title: Add `std.typecons.{callFunction,callNonstaticMemberFunction}` templates

`callNonstaticMemberFunction` is required for wrappers like `emplace` to work properly.

Added templates:
```D
template callFunction(alias wrapperFunc, size_t wrapperOwnArgs, alias func)
{
mixin callFunctionImpl!(wrapperFunc, wrapperOwnArgs);

auto ref callFunction(ref Args refArgs)
{ mixin("return func" ~ callString); }
}

/// ditto
template callNonstaticMemberFunction(alias wrapperFunc, size_t wrapperOwnArgs, T, string funcName)
{
mixin callFunctionImpl!(wrapperFunc, wrapperOwnArgs);

auto ref callNonstaticMemberFunction(ref T t, ref Args refArgs)
{ mixin("return t." ~ funcName ~ callString); }
}

private mixin template callFunctionImpl(alias wrapperFunc, size_t wrapperOwnArgs)
{
// Workaround Issue @@@8995@@@
alias ParameterTypeTuple!wrapperFunc[wrapperOwnArgs .. $] ArgsWithStorageClasses;
template DeStorage(T) { alias T DeStorage; }
alias staticMap!(DeStorage, ArgsWithStorageClasses) Args;

T rvalueOf(T)(ref T t)
{ return move(t); }

enum callString =
{
string argsStr;
foreach(i, storageClass; parameterStorageClassTuple!wrapperFunc[wrapperOwnArgs .. $])
{
enum byRef = !!(storageClass & (ParameterStorageClass.ref_ | ParameterStorageClass.out_));
if(i) argsStr ~= ',';
import std.string;
argsStr ~= xformat(byRef ? "%s" : "rvalueOf(%s)", xformat("refArgs[%s]", i));
}
return "(" ~ argsStr ~ ");";
}();
}
```

Requirements:
* `parameterStorageClassTuple` from pull #904.

Requires: #904