View mode: basic / threaded / horizontal-split · Log in · Help
September 22, 2012
Testing for template argument being result of takeExactly
I'm trying to test whether a template argument is the type returned by 
takeExactly, and I haven't been able to sort out the template voodoo required 
yet. It would be a lot easier if I had a variable to work with, but I just 
have the type, and the fancy is expression required to pull it off is fancy 
enough that I haven't been able to sort it out yet. At present, I have this:

import std.range;
import std.stdio;

template Hello(R)
   if(is(R r == U, V, V w, U = typeof(takeExactly(w, 1))))
{
   alias R Hello;
}

void main()
{
   auto str = "hello";
   auto t = takeExactly(str, 3);
   writeln(t);
   Hello!(typeof(t)) h = t;
   writeln(h);
}


I need Hello to instatiate if R is the type returned by takeExactly and fail 
to instantiate otherwise. At present, the code gives these compilation errors:

q.d(15): Error: template instance Hello!(Result) Hello!(Result) does not match 
template declaration Hello(R) if (is(R r == U,V,V w,U = 
typeof(takeExactly(w,1))))
q.d(15): Error: Hello!(Result) is used as a type
q.d(16): Error: template std.stdio.writeln does not match any function 
template declaration
q.d(16): Error: template std.stdio.writeln(T...) cannot deduce template 
function from argument types !()(_error_)

So, clearly I don't have the is expression right, and this is seriously 
pushing the edge of my knowledge of is expressions. So, any help would be 
appreciated. Thanks.

- Jonathan M Davis
September 23, 2012
Re: Testing for template argument being result of takeExactly
Jonathan M Davis:

> So, clearly I don't have the is expression right, and this is 
> seriously pushing the edge of my knowledge of is expressions.
> So, any help would be appreciated. Thanks.

I have done some tries, but I have failed, I am sorry :-)
The is() syntax is a part of D good to burn on a campfire.
But takeExactly returns a Result struct defined inside it, so it 
even possible for the is() syntax to work on this inner (hidden?) 
type? Generally the idea of defining structs inside looks nice, 
but seems a source for troubles.

Bye,
bearophile
September 23, 2012
Re: Testing for template argument being result of takeExactly
On Sunday, September 23, 2012 02:57:36 bearophile wrote:
> Jonathan M Davis:
> > So, clearly I don't have the is expression right, and this is
> > seriously pushing the edge of my knowledge of is expressions.
> > So, any help would be appreciated. Thanks.
> 
> I have done some tries, but I have failed, I am sorry :-)
> The is() syntax is a part of D good to burn on a campfire.

The power that it provides is useful if not outright necessary, but it could 
definitely use some improvements in the usability camp once you go beyond the 
basics. But I don't even know how you'd go about designing it so that it was 
more user friendly.

> But takeExactly returns a Result struct defined inside it, so it
> even possible for the is() syntax to work on this inner (hidden?)
> type? Generally the idea of defining structs inside looks nice,
> but seems a source for troubles.

Yeah. Increasingly, it looks like Voldemort types are a bad idea as nice as 
they are in principle. But we have yet to reach the point where it's clear 
that we need to ditch them. We may yet get there though.

- Jonathan M Davis
September 23, 2012
Re: Testing for template argument being result of takeExactly
On 09/23/2012 01:54 AM, Jonathan M Davis wrote:
> I'm trying to test whether a template argument is the type returned by
> takeExactly, and I haven't been able to sort out the template voodoo required
> yet.  It would be a lot easier if I had a variable to work with, but I just
> have the type, and the fancy is expression required to pull it off is fancy
> enough that I haven't been able to sort it out yet. At present, I have this:
>
> import std.range;
> import std.stdio;
>
> template Hello(R)
>      if(is(R r == U, V, V w, U = typeof(takeExactly(w, 1))))
> {
>      alias R Hello;
> }
>
> void main()
> {
>      auto str = "hello";
>      auto t = takeExactly(str, 3);
>      writeln(t);
>      Hello!(typeof(t)) h = t;
>      writeln(h);
> }
>
>
> I need Hello to instatiate if R is the type returned by takeExactly and fail
> to instantiate otherwise. At present, the code gives these compilation errors:
>
> q.d(15): Error: template instance Hello!(Result) Hello!(Result) does not match
> template declaration Hello(R) if (is(R r == U,V,V w,U =
> typeof(takeExactly(w,1))))
> q.d(15): Error: Hello!(Result) is used as a type
> q.d(16): Error: template std.stdio.writeln does not match any function
> template declaration
> q.d(16): Error: template std.stdio.writeln(T...) cannot deduce template
> function from argument types !()(_error_)
>
> So, clearly I don't have the is expression right, and this is seriously
> pushing the edge of my knowledge of is expressions. So, any help would be
> appreciated. Thanks.
>
> - Jonathan M Davis
>

import std.range, std.traits;
import std.stdio;
template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){
    alias R Hello;
}

void main(){
    auto str = "hello";
    auto t = takeExactly(str, 3);
    writeln(t);
    Hello!(typeof(t)) h = t;
    writeln(h);
}
September 23, 2012
Re: Testing for template argument being result of takeExactly
On 9/23/12 8:47 AM, Timon Gehr wrote:
> import std.range, std.traits;
> import std.stdio;
> template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){
> alias R Hello;
> }

That's the nicest. Regarding availability of "_input", I meant to make 
it available systematically as "input" for ranges where the notion makes 
sense.

Andrei
September 23, 2012
Re: Testing for template argument being result of takeExactly
On 09/23/2012 03:48 PM, Andrei Alexandrescu wrote:
> On 9/23/12 8:47 AM, Timon Gehr wrote:
>> import std.range, std.traits;
>> import std.stdio;
>> template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){
>>     alias R Hello;
>> }
>
> That's the nicest.

Well, I noticed it is not entirely correct as takeExactly special cases
sliceable inputs. Therefore, the guard also passes for ranges that have
a sliceable member called _input of the same range type. The correct
guard therefore would be:

if(hasSlicing!R || is(typeof(R._input.takeExactly(2)) == R))

or

if(!hasSlicing!R && is(typeof(R._input.takeExactly(2)) == R))

depending on what the goal is.


> Regarding availability of "_input", I meant to make
> it available systematically as "input" for ranges where the notion makes
> sense.
>
> Andrei

This seems to be reasonable.
September 23, 2012
Re: Testing for template argument being result of takeExactly
On Saturday, 22 September 2012 at 23:53:28 UTC, Jonathan M Davis 
wrote:
> I'm trying to test...
> [SNIP]
> - Jonathan M Davis

I *kind of* see what you are doing with U, V, W, but what's wrong 
with just doing:

----
import std.range;

template Hello(R)
   if(is(typeof(R == typeof(takeExactly(R, 1)))))
{
   alias R Hello;
}

struct S;

void main( ) {
    Hello!(int[]) a; //OK
    Hello!S b;       //FAIL
}
----
?

It seems to work for me..., but I'm not 100% sure there isn't 
something illegal/unsafe in there.
September 23, 2012
Re: Testing for template argument being result of takeExactly
On 09/23/2012 12:02 PM, monarch_dodra wrote:
> On Saturday, 22 September 2012 at 23:53:28 UTC, Jonathan M Davis wrote:
>> I'm trying to test...
>> [SNIP]
>> - Jonathan M Davis
>
> I *kind of* see what you are doing with U, V, W, but what's wrong with
> just doing:
>
> ----
> import std.range;
>
> template Hello(R)
> if(is(typeof(R == typeof(takeExactly(R, 1)))))
> {
> alias R Hello;
> }
>
> struct S;
>
> void main( ) {
> Hello!(int[]) a; //OK
> Hello!S b; //FAIL
> }
> ----
> ?
>
> It seems to work for me..., but I'm not 100% sure there isn't something
> illegal/unsafe in there.

The goal is to "test whether a template argument is the type returned by 
takeExactly."

Your solution (I think) is looking at a container and determining 
whether the type of that container can be compared to the return type of 
takeExactly(). (Note that typeof(X == Y) is used for checking whether 
that expression itself is valid.)

Also, I think your code should have passed a range like R.init to 
takeExactly, not R, which is a type:

  takeExactly(R.init, 1)

I don't know why your code compiles.

Ali
September 23, 2012
Re: Testing for template argument being result of takeExactly
On Sunday, 23 September 2012 at 20:56:42 UTC, Ali Çehreli wrote:
> On 09/23/2012 12:02 PM, monarch_dodra wrote:
> > On Saturday, 22 September 2012 at 23:53:28 UTC, Jonathan M
> Davis wrote:
> >> I'm trying to test...
> >> [SNIP]
> >> - Jonathan M Davis
> >
> > I *kind of* see what you are doing with U, V, W, but what's
> wrong with
> > just doing:
> >
> > ----
> > import std.range;
> >
> > template Hello(R)
> > if(is(typeof(R == typeof(takeExactly(R, 1)))))
> > {
> > alias R Hello;
> > }
> >
> > struct S;
> >
> > void main( ) {
> > Hello!(int[]) a; //OK
> > Hello!S b; //FAIL
> > }
> > ----
> > ?
> >
> > It seems to work for me..., but I'm not 100% sure there isn't
> something
> > illegal/unsafe in there.
>
> The goal is to "test whether a template argument is the type 
> returned by takeExactly."
>
> Your solution (I think) is looking at a container and 
> determining whether the type of that container can be compared 
> to the return type of takeExactly(). (Note that typeof(X == Y) 
> is used for checking whether that expression itself is valid.)

Good point. My bad then.

> Also, I think your code should have passed a range like R.init 
> to takeExactly, not R, which is a type:
>
>   takeExactly(R.init, 1)
>
> I don't know why your code compiles.

That did seem fishy to me too actually, but it does compile.

> Ali

In that case, what about:

--------
import std.range;

template Hello(R)
    if(is(typeof(takeExactly(R.init, 1))) && is(R ==
typeof(takeExactly(R.init, 1))))
{
    alias R Hello;
}

struct S{};

void main( ) {
     Hello!(int[]) a; //OK
     Hello!S b;       //FAIL (again)
}
-------
September 23, 2012
Re: Testing for template argument being result of takeExactly
On 09/23/2012 10:57 PM, Ali Çehreli wrote:
> ...
>
> Also, I think your code should have passed a range like R.init to
> takeExactly, not R, which is a type:
>
>    takeExactly(R.init, 1)
>
> I don't know why your code compiles.
>

See discussion here:
http://d.puremagic.com/issues/show_bug.cgi?id=8220
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home