Implicit type conversion of an argument when a function is called
John Colvin
john.loughran.colvin at gmail.com
Tue Feb 11 08:10:51 PST 2014
On Tuesday, 11 February 2014 at 14:47:31 UTC, Carl Sturtivant
wrote:
>> With a class you can do this:
>> class Data
>> {
>> string s;
>> this(string s)
>> {
>> this.s = s;
>> }
>> }
>>
>> void f(Data x ...)
>> {
>> import std.stdio;
>> writeln(x.s);
>> }
>>
>> void main()
>> {
>> f("hello"); //convert argument implicitly to type `data`.
>> }
>>
>> See Typesafe Variadic Functions at
>> http://dlang.org/function.html
>>
>> I don't know why you can't do it with a struct.
>>
>> As a workaround, you can do this:
>>
>> class Construct(T)
>> {
>> T t;
>> this(Q)(Q q)
>> {
>> static if(is(Q : T))
>> {
>> t = q;
>> }
>> else
>> {
>> this.t = T(q);
>> }
>> }
>> }
>>
>> struct Data
>> {
>> string s;
>> }
>>
>> void f(Construct!Data xC ...) //construct the wrapper class
>> {
>> auto x = xC.t; //get the contents.
>>
>> import std.stdio;
>> writeln(x.s);
>> }
>>
>> void main()
>> {
>> f("hello");
>> f(Data("world"));
>> }
>>
>>
>> Overall it's probably best to define f as:
>>
>> void f(Data x)
>> {
>> import std.stdio;
>> writeln(x.s);
>> }
>>
>> void f(Construct!Data xC ...)
>> {
>> .f(xC.t);
>> }
>>
>> To avoid any overhead when calling normally as well as
>> separating the definition of the real function from the
>> concern of automatic construction/conversion.
>
> Nice technique, I'll remember that. Presumably this can't be
> extended to functions with more than one Data parameter.
You are correct, although you can of course just create a normal
D-style variadic function overload that does any conversions
necessary and then forwards to the original function, but you get
less of a helping hand from the language. In general it's harder
as you could have multiple constructors that take different
numbers of arguments. My example above should work for any number
of args, but if you restrict yourself to 1 to 1 conversions:
void g(A a, B b) {}
void g(TL ...)(TL args)
if(TL.length == 2)
{
//do conversions if possible and pass the converted args to
//g(A,B).
}
In all of this I haven't taken any care over ref-ness. In order
to get that correct you likely need to use auto ref and maybe
std.algorithm.forward, I haven't thought much about it.
More information about the Digitalmars-d-learn
mailing list