www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - normal function and template function conflict

reply "monarch_dodra" <monarchdodra gmail.com> writes:
I was trying to write a PRNG, and I wanted to give it two seed 
methods. The first is to seed from a unique UIntType, and the 
other is to seed from an entire range of seeds. Like so:

--------
void seed(UIntType value = default_seed)
{...}

void seed(Range)(Range range)
   if (isInputRange!Range)
{...}
--------
Where UIntType is a template parameter of the struct.

However, this makes the compiler complain, because of a 
conflict...? Is mixing normal functions with parametrized ones 
impossible?

I *fixed* the issue by contemplating the first call with:
--------
void seed(T)(T value = default_seed)
   if (is(typeof(T == UIntType)))
{...}
--------
Problems:
1) It is ugly as sin.
2) The default parameter doesn't work anymore.

So here are my two questions:
1) Is what I was originally trying to do actually illegal, or is 
it some sort of compiler limitation? TDPL implies this should 
work perfectly fine...
2) Is there a "correct" workaround?
Jul 26 2012
next sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Thu, 26 Jul 2012 19:18:21 +0200, monarch_dodra <monarchdodra gmail.com>  
wrote:

 So here are my two questions:
 1) Is what I was originally trying to do actually illegal, or is it some  
 sort of compiler limitation? TDPL implies this should work perfectly  
 fine...

Compiler limitation. It's supposed to work.
 2) Is there a "correct" workaround?

Exactly what you did. Though, for brevity, you would write this: void seed(T : UIntType)(T value = default_seed) -- Simen
Jul 26 2012
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/26/2012 11:14 AM, monarch_dodra wrote:
 On Thursday, 26 July 2012 at 17:57:31 UTC, Simen Kjaeraas wrote:
 On Thu, 26 Jul 2012 19:18:21 +0200, monarch_dodra
 <monarchdodra gmail.com> wrote:
 2) Is there a "correct" workaround?

Exactly what you did. Though, for brevity, you would write this: void seed(T : UIntType)(T value = default_seed)

Thanks I haven't seen this construct before. Can you tell me a bit more about it, or link me to some documentation about it? I suppose it means "T must be UIntType", but I'd enjoy having a broader understanding of it :)

Search for "specialization" in the following resources: http://dlang.org/template.html https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/dtemplates.pdf http://ddili.org/ders/d.en/templates.html Ali
Jul 26 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-07-26 19:57, Simen Kjaeraas wrote:

 2) Is there a "correct" workaround?

Exactly what you did. Though, for brevity, you would write this: void seed(T : UIntType)(T value = default_seed)

Since a template function is actually not wanted this would be the correct workaround: void seed () (UIntType value = default_seed) Less typing as well. -- /Jacob Carlborg
Jul 26 2012
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 26 July 2012 at 17:57:31 UTC, Simen Kjaeraas wrote:
 On Thu, 26 Jul 2012 19:18:21 +0200, monarch_dodra 
 <monarchdodra gmail.com> wrote:
 2) Is there a "correct" workaround?

Exactly what you did. Though, for brevity, you would write this: void seed(T : UIntType)(T value = default_seed)

Thanks I haven't seen this construct before. Can you tell me a bit more about it, or link me to some documentation about it? I suppose it means "T must be UIntType", but I'd enjoy having a broader understanding of it :)
Jul 26 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Thu, 26 Jul 2012 20:14:10 +0200, monarch_dodra <monarchdodra gmail.com>  
wrote:

 On Thursday, 26 July 2012 at 17:57:31 UTC, Simen Kjaeraas wrote:
 On Thu, 26 Jul 2012 19:18:21 +0200, monarch_dodra  
 <monarchdodra gmail.com> wrote:
 2) Is there a "correct" workaround?

Exactly what you did. Though, for brevity, you would write this: void seed(T : UIntType)(T value = default_seed)

Thanks I haven't seen this construct before. Can you tell me a bit more about it, or link me to some documentation about it? I suppose it means "T must be UIntType", but I'd enjoy having a broader understanding of it :)

Ali gave the general, I'll give the specifics. is(T : Foo), void bar(T : Foo)(T t), and a few others (not really others, they're exactly the same!) means 'T is implicitly convertible to Foo'. What's the difference, you ask? Consider: void foo(T)(T value) if (is(T == uint)) {} Could you call this function like this: foo(3); The answer is no. The compiler translates this to: foo!(typeof(3))(3); And typeof(3) is not uint, it's int. In contrast, void foo(T : uint)(T value) {} foo(3); is also translated to foo!(typeof(3))(3); and the compiler then checks if int is implicitly convertible to uint. And so it is, so the compiler moves happily onwards. There is a reason I included is(T : Foo) in the beginning, for you can write the exact same constraint like this: void foo(T)(T value) if (is(T : uint)) {} and it will compile just the same. For more information on this construct, I would, in addition to the links Ali provided, recommend you read this: http://dlang.org/expression.html#IsExpression IsExpressions are, however, probably the most hairy part of D, and their understanding has proven troublesome to many (myself included, though I believe I have grasped them now). Hence, most of their functionality is wrapped in more easily understandable templates in std.traits. -- Simen
Jul 26 2012
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 26 July 2012 at 18:21:18 UTC, Ali Çehreli wrote:
 Search for "specialization" in the following resources:

Oh... "Specialization". What with D's ability to conditionally implement, I had completely forgotten about specialization. So that's how it's done in D. Cool. Thanks a lot.
Jul 26 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/26/12, Jacob Carlborg <doob me.com> wrote:
 void seed () (UIntType value = default_seed)

 Less typing as well.

Yep. It's funny how this works at all. I mean a template with no template parameters is somehow still a template. :)
Jul 26 2012
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, July 26, 2012 21:49:35 Andrej Mitrovic wrote:
 On 7/26/12, Jacob Carlborg <doob me.com> wrote:
 void seed () (UIntType value = default_seed)
 
 Less typing as well.

Yep. It's funny how this works at all. I mean a template with no template parameters is somehow still a template. :)

It _is _ bit funny, but Ibelieve that it comes from permitting empty template parameter lists. Without that, recursion with eponymous templates would become problematic. e.g. enum template myTemplate(T...) { static if(T.length == 0) enum myTemplate = 42; else enum myTemplate = T[0] * 3 + myTemplate!(T[1 .. $]); } needs to be able to take an empty parameter list. It's probably possible to make that work without allowing an outright empty parameter list that isn't even a variadic template, but I suspect that it's just easier to allow it. - Jonathan M Davis
Jul 26 2012