TDPL: Overloading template functions

Andrej Mitrovic andrej.mitrovich at gmail.com
Thu Jul 29 14:28:02 PDT 2010


How do I print out an expanded tuple but with spaces between the values?
There's this example on page 164:

import std.typecons, std.stdio;

void fun(T...)(T args) {
    // create a tuple to pack all arguments together
    gun(tuple(args));
}

void gun(T)(T value) {
    // expand the tuple back
    writeln(value.expand);
}

void main() {
    fun(1);
    fun(1, 2.2);
}

This prints out:
1
12.2

But that's confusing, since the values are "glued" together when printed
out. I really want to print out:
1
1 2.2

Any ideas?

One other thing. I can use the .length property for value and parameter
tuples, but only if I haven't built them myself with the call to
std.typecons.tuple(). For example I can call writeln(T.length) in the fun()
function (where the compiler automatically constructs a tuple), but not in
the gun() function. So there seems to be compiler tuples and
user-constructed tuples, which are not the same.

It's a bit of a shame that there isn't a chapter on tuples except this brief
mention (I don't see it listed in the contents page). I guess I'll take a
look at the implementation.

On Thu, Jul 29, 2010 at 5:08 PM, Andrej Mitrovic <andrej.mitrovich at gmail.com
> wrote:

> Page 160, code:
>
> import std.algorithm, std.range;
>
> void main() {}
>
> double average() { return 1.0; }
> double average(double) { return 2.0; }
>
> // computes average of a set of numbers, passable directly or via an array
> double average(double[] values...) {
>     if (values.empty) {
>         throw new Exception("Average of zero elements in undefined");
>     }
>     return reduce!((a, b) { return a + b; })(0.0, values) / values.length;
> }
>
> unittest {
>     average();
>     average(2.5);
> }
>
>
> The book states this is an ambiguous call, but I can succesfully compile.
>
>
> On Thu, Jul 29, 2010 at 4:16 AM, Andrej Mitrovic <
> andrej.mitrovich at gmail.com> wrote:
>
>> I can't get the example on page 158 to compile, I've tried both versions
>> of reduce:
>>
>> import std.stdio, std.range;
>>
>> @property bool empty(T)(T[] a) { return a.length == 0; }
>> @property ref T front(T)(T[] a) { return a[0]; }
>> void popFront(T)(ref T[] a) { a = a[1 .. $]; }
>>
>> V reduce(alias fun, V, R)(V x, R range)
>>     if (isInputRange!R && is(typeof(x = fun(x, range.front))))
>> {
>>     for (; !range.empty; range.popFront()) {
>>         x = fun(x, range.front);
>>     }
>>     return x;
>> }
>>
>> unittest {
>>     int[] r = [10, 14, 3, 5, 23];
>>
>>     // compute the sum of all elements
>>     int sum = reduce!((a, b) { return a + b; })(0, r);
>>     assert(sum == 55);
>>
>>     // compute minimum
>>     int min = reduce!((a, b) { return a < b ? a : b; })(r[0], r);
>>     assert(min == 3);
>> }
>>
>> void main() { }
>>
>> Errors:
>> reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if
>> (isInputRange!(R) && is(typeof(x = fun(x,range.front)))) does not match any
>> function template declaration
>>
>> reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if
>> (isInputRange!(R) && is(typeof(x = fun(x,range.front)))) cannot deduce
>> template function from argument types !(__dgliteral1)(int,int[])
>>
>> reduce.d(31): Error: template instance errors instantiating template
>>
>> If I comment out the template constraints (the if statements for either
>> version of reduce), the example will compile and the unittests will pass.
>>
>>
>> On Wed, Jul 28, 2010 at 11:15 PM, Andrej Mitrovic <
>> andrej.mitrovich at gmail.com> wrote:
>>
>>> Should I just keep posting my findings in this thread? I hate to make a
>>> new thread for every problem I find..
>>>
>>> Anyway, on Page 150, this code fails:
>>>
>>> auto f = (int i) {};
>>> assert(is(f == function));
>>>
>>> I've checked via typeid(), and f is a delegate by default, not a
>>> function. I've tested it both in a function's scope and in module scope,
>>> with the same results.
>>>
>>>
>>> On Wed, Jul 28, 2010 at 10:56 PM, Rainer Schuetze <r.sagitario at gmx.de>wrote:
>>>
>>>>
>>>> Andrej Mitrovic wrote:
>>>>
>>>>> Woops, I got confused. I was thinking about structs, not arrays.
>>>>>
>>>>>
>>>>> But yeah, in this case a float gets compared to a double and it seems
>>>>> to evaluate to false.
>>>>>
>>>>
>>>> 2.4 has no exact representation as a floating point value, as it is
>>>> 2^^2*0.6, so the mantissa is 3/5. It is rounded after 24 bits for float, but
>>>> after 53 bits for a double. As a result
>>>>
>>>>        float f = 2.4; // approximately 2.4000001
>>>>        double d = 2.4; // approximately 2.3999999999999999
>>>>        assert(f == d);
>>>>
>>>> fails, because the comparison is done after converting the truncated
>>>> float to double (as long as the compiler does not issue SSE instructions
>>>> with single precision).
>>>>
>>>> In contrast, this
>>>>
>>>>        assert(2.4 == 2.4f);
>>>>
>>>> passes, as the compiler keeps real precision until writing the value to
>>>> memory and evaluates the expression at compile time.
>>>>
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20100729/809418b2/attachment-0001.html>


More information about the Digitalmars-d mailing list