Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 57 additions & 30 deletions std/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -1016,8 +1016,11 @@ template arity(alias func)
}

/**
Returns a tuple consisting of the storage classes of the parameters of a
function $(D func).
Get tuple, one per function parameter, of the storage classes of the parameters.
Params:
func = function symbol or type of function, delegate, or pointer to function
Returns:
A tuple of ParameterStorageClass bits
*/
enum ParameterStorageClass : uint
{
Expand All @@ -1037,39 +1040,28 @@ enum ParameterStorageClass : uint
template ParameterStorageClassTuple(func...)
if (func.length == 1 && isCallable!func)
{
alias Func = Unqual!(FunctionTypeOf!func);

/*
* TypeFuncion:
* CallConvention FuncAttrs Arguments ArgClose Type
*/
alias Params = Parameters!Func;
alias Func = FunctionTypeOf!func;

// chop off CallConvention and FuncAttrs
enum margs = demangleFunctionAttributes(mangledName!Func[1 .. $]).rest;

// demangle Arguments and store parameter storage classes in a tuple
template demangleNextParameter(string margs, size_t i = 0)
static if (is(Func PT == __parameters))
{
static if (i < Params.length)
template StorageClass(size_t i)
{
enum demang = demangleParameterStorageClass(margs);
enum skip = mangledName!(Params[i]).length; // for bypassing Type
enum rest = demang.rest;

alias demangleNextParameter =
AliasSeq!(
demang.value + 0, // workaround: "not evaluatable at ..."
demangleNextParameter!(rest[skip .. $], i + 1)
);
}
else // went thru all the parameters
{
alias demangleNextParameter = AliasSeq!();
static if (i < PT.length)
{
alias StorageClass = AliasSeq!(
extractParameterStorageClassFlags!(__traits(getParameterStorageClasses, Func, i)),
StorageClass!(i + 1));
}
else
alias StorageClass = AliasSeq!();
}
alias ParameterStorageClassTuple = StorageClass!0;
}
else
{
static assert(0, func[0].stringof ~ " is not a function");
alias ParameterStorageClassTuple = AliasSeq!();
}

alias ParameterStorageClassTuple = demangleNextParameter!margs;
}

///
Expand All @@ -1087,6 +1079,41 @@ template ParameterStorageClassTuple(func...)
static assert(pstc[2] == STC.none);
}

/*****************
* Convert string tuple Attribs to ParameterStorageClass bits
* Params:
* Attribs = string tuple
* Returns:
* ParameterStorageClass bits
*/
template extractParameterStorageClassFlags(Attribs...)
{
enum ParameterStorageClass extractParameterStorageClassFlags = ()
{
auto result = ParameterStorageClass.none;
static if (Attribs.length > 0)
{
foreach (attrib; [Attribs])
{
final switch (attrib) with (ParameterStorageClass)
{
case "scope": result |= scope_; break;
case "out": result |= out_; break;
case "ref": result |= ref_; break;
case "lazy": result |= lazy_; break;
case "return": result |= return_; break;
}
}
/* Mimic behavor of original version of ParameterStorageClassTuple()
* to avoid breaking existing code.
*/
if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_))
result = ParameterStorageClass.return_;
}
return result;
}();
}

@safe unittest
{
alias STC = ParameterStorageClass;
Expand Down