What does __parameters return?

H. S. Teoh hsteoh at quickfur.ath.cx
Thu Sep 12 12:40:05 PDT 2013


On Thu, Sep 12, 2013 at 08:44:29PM +0200, simendsjo wrote:
> The documentation says "the parameter tuple of a function, delegate,
> or function pointer. This includes the parameter types, names, and
> default values."
> 
> .. but what type is it?
> 
> Error: argument (int i, char c, string s, bool b = false) to typeof
> is not an expression
> 
> How am I supposed to get the parameter names using this?
> 
> It's possible to use .stringof, and then regular string handling to
> extract the names, but I guess there should be a simpler way if only
> I knew what it returned.

You're not going to like the answer to this one... :)

Here's some example code that uses __parameters to inspect a function
and print out a list of its parameter types and names (my explanations
are in the comments):

-------------snip-------------
import std.stdio;

// Example function we want to examine parameters for
int func(string x, float y, int z=123) {
	return 0;
}

void main() {
	// __parameters appears to only work inside is(...), in a quirky
	// special-cased syntax that ONLY works when written exactly in the
	// form is(TypeOfFunc Ident == __parameters), in which case Ident gets
	// aliased to a "parameter tuple", an elusive compiler internal entity
	// that is similar to, but not the same as, a "type tuple".
	static if (is(typeof(func) Params == __parameters)) {
		// You already know what does one this, I believe.
		pragma(msg, Params.stringof);

		// foreach works on parameter tuples, but it acts very weird.
		// If a single argument is given, it gets assigned to the
		// *type* of the parameter in question. If two arguments are
		// given, like here, the first is assigned the index into the
		// parameter tuple, and the second to the *type* of the
		// corresponding parameter.
		foreach (i, T; Params) {
			// This quirky behaviour of foreach on parameter tuples
			// means T is *not* the parameter itself, merely the
			// *type* of the parameter. To get the actual
			// parameter's description, we need a 1-element slice
			// of the parameter tuple. Thankfully, i has been
			// conveniently assigned the index of the current
			// parameter, so we can use that for the slicing:
			alias Param = Params[i .. i+1];

			// As I said, T is merely the type of the parameter,
			// not the parameter itself.
			alias ParamType = T;

			// The 1-element slice Param behaves as if it's an
			// independent entity with a name, so we can use
			// __traits(identifer, ...) to get at the parameter
			// name.
			string ParamName = __traits(identifier, Param);

			writeln("type=", T.stringof, " name=", ParamName);

			// Not shown here is the default parameter value.
			// Looking at std.traits.ParameterDefaultValueTuple,
			// there appears to be no direct way to get at this.
			// The only way seems to be to declare a function with
			// Param as its single argument, and then call that
			// function with no arguments so that the function can
			// return the default value of the parameter. This is
			// what Phobos actually does to build the default
			// parameter tuple.

			// Also not shown here is how to get at the
			// storage class of the parameter; I didn't look
			// into this, but your best reference would be
			// std.traits.ParameterStorageClass' code.
		}
	}
}
-------------snip-------------

Given the non-intuitive quirkiness of the whole thing, you're probably
far better off using Phobos' std.traits.Parameter...Tuple templates to
get at the various bits of function parameters.

Or just parse the string returned by the .stringof value, as you
suggested.


T

-- 
Never wrestle a pig. You both get covered in mud, and the pig likes it.


More information about the Digitalmars-d-learn mailing list