www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Accessing template parameters from outside?

reply Norbert Nemec <Norbert Nemec-online.de> writes:
As far as I can see, an IsExpression allows to check whether T is an
exact type, but is there a possibilty to check whether T is an instance
of a certain template with arbitrary parameter? Like:

	is(T:mytemplate!(???))

Even more: once I know that T is an instance of mytemplate, is there a
way to find out what the template parameters are?

Basically, what would be needed is some pattern matching mechanism like:

	if(is(T:mytemplate($N)))

where the IsExpression is true if the pattern fits, and at the same
time, the "wildcard" $N is assigned to whatever it matches.

The whole thing is inspired by the template mechanism of C++ which
allows the following:

--------------------
template<int N> class vector {
	double data[N];
}

template<typename T> class container {
	T content;
	void dump() {
		cout << "Container for unknown type\n";
	}
}

// simple specialization
template<> class container<double> {
	double content;
	void dump() {
		cout << "Container for double\n";
	}
}

// specialization for template as parameter:
template<int N> class container<vector<N> > {
	vector<N> content;
	void dump() {
		cout << "Container for vector of size " << N << "\n";
	}
}

container<int> icontainer;
icontainer.dump();
// prints: "Container for unknown type"

container<double > dcontainer;
dcontainer.dump();
// prints: "Container for double"

container<vector<3> > vcontainer;
vcontainer.dump();
// prints: "Container for vector of size 3"
---------------------

Meaning: inside the specialized template, I can, at compile time,
analyse the parameters.

The corresponding code in D would like something like:

---------------------
class vector(int N) {
	double[N] data;
};

class container(T) {
	T content;
	void dump() {
		static if(is(T:double)) {
			printf("Container for double\n");
		} else static if(is(T:vector ?????)
			printf("Container for vector %i\n",?????);
		} else {
			printf("Container for unknown type\n");
		}
	}
};
---------------------

How should I write the lines containing the "?????"? I know the example
above it stupid, but the core point itself came up when I tried several
solutions in for the units library yesterday. I found ugly workarounds,
but no real solution.
Apr 24 2006
parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Norbert Nemec skrev:
 As far as I can see, an IsExpression allows to check whether T is an
 exact type, but is there a possibilty to check whether T is an instance
 of a certain template with arbitrary parameter? Like:
 
 	is(T:mytemplate!(???))
 
 Even more: once I know that T is an instance of mytemplate, is there a
 way to find out what the template parameters are?
 
 Basically, what would be needed is some pattern matching mechanism like:
 
 	if(is(T:mytemplate($N)))
 

 
 The corresponding code in D would like something like:
 
 ---------------------
 class vector(int N) {
 	double[N] data;
 };
 
 class container(T) {
 	T content;
 	void dump() {
 		static if(is(T:double)) {
 			printf("Container for double\n");
 		} else static if(is(T:vector ?????)
 			printf("Container for vector %i\n",?????);
 		} else {
 			printf("Container for unknown type\n");
 		}
 	}
 };
 ---------------------
 
 How should I write the lines containing the "?????"? I know the example
 above it stupid, but the core point itself came up when I tried several
 solutions in for the units library yesterday. I found ugly workarounds,
 but no real solution.

The shortest fix to do the above I can think of is: } else static if(is(typeof(content.data))) { printf("Container for vector %i\n",content.data.length); Another way is: class vector(int N) { const vector_N = N; double[N] data; } ... } else static if(is(typeof(T.vector_N))) { printf("Container for vector %i\n",T.vector_N); But I guess those are what you call ugly workarounds. I don't think there is any nice general way to get the arguments of an instantiated template. But you can if you make sure all your templates have alias and const parameters corresponding to the template parameters. I guess you could even check the .mangleof property of the type at compile time to make sure it is an instantiation of a certain template. (You could even get the template parameters from the mangled name...) More often, I think one would have more use of checking that a certain type has certain properties rather than specializing for a specific template. I.e: // A queue is something that has push_back and pop_front methods. template IsQueue(T) { static if (is(typeof(T.push_back)) && is(typeof(T.pop_front))) const bool IsQueue = true; else const bool ISQueue = false; } (This could of course be made much better) /Oskar
Apr 25 2006
next sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Oskar Linde wrote:
 Norbert Nemec skrev:
 [snip]
 
 More often, I think one would have more use of checking that a certain
 type has certain properties rather than specializing for a specific
 template. I.e:
 
 [snip]
 
 /Oskar

What about my Python bindings that I'm trying to write? In that case, I *need* to know the exact type in order to build things like argument unpacking calls. I ran into this almost exact same problem trying to determine the types of the arguments in function pointers. After trying for several days, I just assume that it can't be done. I don't really want to add any further burden on Walter for 1.0, but is there any chance we'll see either multiple type inference (say, (Ta,Tb) : Ta function(Tb)), or be able to pass in wildcards to the templates (like Ta : Ta function(AnyType))? -- Daniel -- v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 25 2006
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Oskar Linde wrote:
<snip>
 The shortest fix to do the above I can think of is:
 
   } else static if(is(typeof(content.data))) {
     printf("Container for vector %i\n",content.data.length);

How about is(T : vector!(content.data.length))) which will make sure it really is a vector and not just an arbitrary type with a member called data? But I think you're right that the only solution we have at the moment is to use template-specific features. Stewart.
Apr 25 2006