www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Testing for template argument being result of takeExactly

reply Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Sep 22 2012
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
Sep 22 2012
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Sep 22 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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); }
Sep 23 2012
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
Sep 23 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
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.
Sep 23 2012
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, September 23, 2012 14:47:27 Timon Gehr wrote:
 template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){
      alias R Hello;
 }
Thanks. That does the trick quite cleanly, though you'd think that it would be possible to test whether a template argument is the result of takeExactly without caring or knowing about the guts of takeExactly. So, this isn't a general purpose solution at all, when I think that there should be one. Still, I don't need a general purpose one for what I'm doing, so this should work just fine. - Jonathan M Davis
Sep 23 2012
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Sunday, 23 September 2012 at 21:52:23 UTC, Timon Gehr wrote:
 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
Interesting. Thanks. On Sunday, 23 September 2012 at 21:53:20 UTC, Jonathan M Davis wrote:
 On Sunday, September 23, 2012 14:47:27 Timon Gehr wrote:
 template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){
      alias R Hello;
 }
Thanks. That does the trick quite cleanly, though you'd think that it would be possible to test whether a template argument is the result of takeExactly without caring or knowing about the guts of takeExactly. So, this isn't a general purpose solution at all, when I think that there should be one. Still, I don't need a general purpose one for what I'm doing, so this should work just fine. - Jonathan M Davis
What is wrong with my proposed solution? ---- import std.range; template Hello(R) if ( is(typeof(takeExactly(R.init, 1))) && is(R == typeof(takeExactly(R.init, 1))) ) { alias R Hello; } struct R { enum empty = false; property int front(); void popFront(); } struct S{} void main( ) { Hello!(int[]) a; //OK Hello!R b; //Fails second Check: R == typeof(...) Hello!S c; //Fails first check: is(typeof(takeExactly(...))) } ---- Forgive me again if there is something wrong with it, but this time, I think it is correct...?
Sep 23 2012
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 24 September 2012 at 06:20:57 UTC, monarch_dodra wrote:
 What is wrong with my proposed solution?
I think I forgot this test, when R is already a type returned by takeExactly: void main( ) { alias typeof(takeExactly(R.init, 5)) G; Hello!G g; } Which also works.
Sep 23 2012
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 24 September 2012 at 06:29:25 UTC, monarch_dodra wrote:
 On Monday, 24 September 2012 at 06:20:57 UTC, monarch_dodra 
 wrote:
 What is wrong with my proposed solution?
I think I forgot this test, when R is already a type returned by takeExactly: void main( ) { alias typeof(takeExactly(R.init, 5)) G; Hello!G g; } Which also works.
Er, sorry for triple post, no edit button. This is R: struct R { enum empty = false; property int front(); void popFront(); } I meant when "Hello' R is already the result of a Take exactly", sorry for the confusion.
Sep 23 2012
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, September 24, 2012 08:21:46 monarch_dodra wrote:
 template Hello(R)
      if ( is(typeof(takeExactly(R.init, 1))) &&
           is(R == typeof(takeExactly(R.init, 1)))
      )
 {
      alias R Hello;
 }
 What is wrong with my proposed solution?
It may work, but again, it's relying on how takeExactly works. It's testing that you can call takeExactly on R.init and then that R is the same type as that result, which means that it's relies on the fact that takeExactly returns itself if you call takeExactly on it. It also relies on init, which can be risky, given the fact that it can be disabled. So, between your prosposal and the other that Philippe and Timon gave, theirs seems better. But unfortunately, none of the proposals work generically. Ideally, there would be a way to generically test that a type is the type returned by particular function, and I would _think_ that that's possible, but the way that I would expect to work doesn't. Regardless, thanks for your help. - Jonathan M Davis
Sep 24 2012
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 24 September 2012 at 07:07:16 UTC, Jonathan M Davis
wrote:
 On Monday, September 24, 2012 08:21:46 monarch_dodra wrote:
 template Hello(R)
      if ( is(typeof(takeExactly(R.init, 1))) &&
           is(R == typeof(takeExactly(R.init, 1)))
      )
 {
      alias R Hello;
 }
 What is wrong with my proposed solution?
It may work, but again, it's relying on how takeExactly works. It's testing that you can call takeExactly on R.init and then that R is the same type as that result, which means that it's relies on the fact that takeExactly returns itself if you call takeExactly on it. It also relies on init, which can be risky, given the fact that it can be disabled. So, between your prosposal and the other that Philippe and Timon gave, theirs seems better. But unfortunately, none of the proposals work generically. Ideally, there would be a way to generically test that a type is the type returned by particular function, and I would _think_ that that's possible, but the way that I would expect to work doesn't. Regardless, thanks for your help. - Jonathan M Davis
Good points. Regarding the ".init" issue, I hadn't thought of that, but it can be worked around pretty easily with an is(R r): -------- template Hello(R) if ( is(R r) && is(typeof(takeExactly(r, 1))) && is(R == typeof(takeExactly(r, 1))) ) { alias R Hello; } -------- After that, I guess it is indeed one implementation detail vs the other. IMO, it really depends on whether or not you'd want "int[]" to be considered the return type of a takeExactly :/ Maybe it is, maybe it ain't.
Sep 24 2012
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, September 24, 2012 09:41:26 monarch_dodra wrote:
 Regarding the ".init" issue, I hadn't thought of that, but it can
 be worked around pretty easily with an is(R r):
 
 --------
 template Hello(R)
       if ( is(R r) &&
            is(typeof(takeExactly(r, 1))) &&
            is(R == typeof(takeExactly(r, 1)))
       )
 {
       alias R Hello;
 }
 --------
That was one trick that I was not aware of. I didn't think that one is expression could have an effect on a later one in the surrounding expression. Cool. Though I would point out that that probably doesn't avoid the init problem, because R r uses R.init (unless is expressions treat it differently, which they may). The normal way to avoid that is to do R r = void; but I don't think that that would work in that is expression. Sometimes disabling init is useful, but it can definitely be problematic. It may ultimately have been a mistake to allow it. I don't know. - Jonathan M Davis
Sep 24 2012
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 24 September 2012 at 07:51:23 UTC, Jonathan M Davis 
wrote:
 On Monday, September 24, 2012 09:41:26 monarch_dodra wrote:
 Regarding the ".init" issue, I hadn't thought of that, but it 
 can
 be worked around pretty easily with an is(R r):
 
 --------
 template Hello(R)
       if ( is(R r) &&
            is(typeof(takeExactly(r, 1))) &&
            is(R == typeof(takeExactly(r, 1)))
       )
 {
       alias R Hello;
 }
 --------
That was one trick that I was not aware of. I didn't think that one is expression could have an effect on a later one in the surrounding expression. Cool. Though I would point out that that probably doesn't avoid the init problem, because R r uses R.init (unless is expressions treat it differently, which they may). The normal way to avoid that is to do R r = void; but I don't think that that would work in that is expression. Sometimes disabling init is useful, but it can definitely be problematic. It may ultimately have been a mistake to allow it. I don't know. - Jonathan M Davis
Well, it does work... struct S { disable this(); } void foo(T)(T i) if ( is(T t)) {} void main() { //S s; //Fail S s = void; foo(s); //Works } I think it makes sense that it works, because "is" doesn't actually validate a compile time syntax, rather it is just declaring that "t can be used as an instance of T", but it is not actually declaring *the variable* "t" itself... Not sure I'm explaining myself. Or I think that's how it works. I've been on a wrong streak lately :/
Sep 24 2012
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, September 24, 2012 10:02:54 monarch_dodra wrote:
 Well, it does work...
 
 struct S
 {
       disable this();
 }
 
 void foo(T)(T i)
      if ( is(T t))
 {}
 
 void main()
 {
      //S s; //Fail
      S s = void;
      foo(s); //Works
 }
 
 I think it makes sense that it works, because "is" doesn't
 actually validate a compile time syntax, rather it is just
 declaring that "t can be used as an instance of T", but it is not
 actually declaring *the variable* "t" itself... Not sure I'm
 explaining myself.
 
 Or I think that's how it works. I've been on a wrong streak
 lately :/
disable this; is pretty broken, so I wouldn't really trust it at this point. http://d.puremagic.com/issues/show_bug.cgi?id=7021 But it wouldn't surprise if is expressions are supposed to act differently. is expressions are arguably too fancy for their own good (well, our good anyway). - Jonathan M Davis
Sep 24 2012
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/24/2012 09:41 AM, monarch_dodra wrote:
 ...

 Regarding the ".init" issue, I hadn't thought of that, but it can
 be worked around pretty easily with an is(R r):

 --------
 template Hello(R)
       if ( is(R r) &&
            is(typeof(takeExactly(r, 1))) &&
            is(R == typeof(takeExactly(r, 1)))
       )
 {
       alias R Hello;
 }
 --------
 After that, I guess it is indeed one implementation detail vs the
 other.
I don't think this does what you think it does. The 'is(R r)' declares r to be an alias for R. So 'r' is a type in that code snippet. Also, is(typeof(takeExactly(R, 1))) && is(R == typeof(takeExactly(R, 1))) can be written in a more compact way as is(typeof(takeExactly(R, 1)) == R)
 IMO, it really depends on whether or not you'd want "int[]" to be
 considered the return type of a takeExactly :/ Maybe it is, maybe
 it ain't.
Sep 24 2012
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 24 September 2012 at 22:13:51 UTC, Timon Gehr wrote:
 On 09/24/2012 09:41 AM, monarch_dodra wrote:
 [SNIP]
I don't think this does what you think it does. The 'is(R r)' declares r to be an alias for R. So 'r' is a type in that code snippet.
Darn :(
 Also, is(typeof(takeExactly(R, 1))) && is(R == 
 typeof(takeExactly(R, 1)))

 can be written in a more compact way as

 is(typeof(takeExactly(R, 1)) == R)
Technically, no: That was my first try, and as mentioned in the first reply, this returns true when the types of takeExactly and R are equal comparable, but does not make sure they are the actually the same types. "is(R == typeof(takeExactly(R, 1)))" Makes sure they are the exact same type, and "is(typeof(takeExactly(R, 1)))" is a short-circuit, to prevent the second test from error'ing if takeExactly!R is not legal.
Sep 24 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 09/25/2012 08:41 AM, monarch_dodra wrote:
 On Monday, 24 September 2012 at 22:13:51 UTC, Timon Gehr wrote:
 On 09/24/2012 09:41 AM, monarch_dodra wrote:
 [SNIP]
I don't think this does what you think it does. The 'is(R r)' declares r to be an alias for R. So 'r' is a type in that code snippet.
Darn :(
 Also, is(typeof(takeExactly(R, 1))) && is(R == typeof(takeExactly(R, 1)))

 can be written in a more compact way as

 is(typeof(takeExactly(R, 1)) == R)
Technically, no: That was my first try, and as mentioned in the first reply, this returns true when the types of takeExactly and R are equal comparable, but does not make sure they are the actually the same types. ...
I assume you messed up the parentheses. is(typeof(takeExactly(R, 1) == R)) // test for equal-comparable is(typeof(takeExactly(R, 1)) == R) // test for type identity alias float flt; static assert(is(typeof(1==flt))); static assert(!is(typeof(1)==flt));
Sep 26 2012
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 26 September 2012 at 13:19:13 UTC, Timon Gehr wrote:
 On 09/25/2012 08:41 AM, monarch_dodra wrote:
 On Monday, 24 September 2012 at 22:13:51 UTC, Timon Gehr wrote:
 On 09/24/2012 09:41 AM, monarch_dodra wrote:
 [SNIP]
I don't think this does what you think it does. The 'is(R r)' declares r to be an alias for R. So 'r' is a type in that code snippet.
Darn :(
 Also, is(typeof(takeExactly(R, 1))) && is(R == 
 typeof(takeExactly(R, 1)))

 can be written in a more compact way as

 is(typeof(takeExactly(R, 1)) == R)
Technically, no: That was my first try, and as mentioned in the first reply, this returns true when the types of takeExactly and R are equal comparable, but does not make sure they are the actually the same types. ...
I assume you messed up the parentheses. is(typeof(takeExactly(R, 1) == R)) // test for equal-comparable is(typeof(takeExactly(R, 1)) == R) // test for type identity alias float flt; static assert(is(typeof(1==flt))); static assert(!is(typeof(1)==flt));
Yes sorry. I miss read that. Kind of weird though, could you explain why: struct S{}; is(typeof(takeExactly(S, 1)) == S) //false is(S == typeof(takeExactly(S, 1))) //Error: template std.range.takeExactly does not match any function template declaration I was under the understanding that == was a commutative operation. Not the case in an is block?
Sep 26 2012
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/26/2012 03:50 PM, monarch_dodra wrote:
 On Wednesday, 26 September 2012 at 13:19:13 UTC, Timon Gehr wrote:
 On 09/25/2012 08:41 AM, monarch_dodra wrote:
 On Monday, 24 September 2012 at 22:13:51 UTC, Timon Gehr wrote:
 On 09/24/2012 09:41 AM, monarch_dodra wrote:
 [SNIP]
I don't think this does what you think it does. The 'is(R r)' declares r to be an alias for R. So 'r' is a type in that code snippet.
Darn :(
 Also, is(typeof(takeExactly(R, 1))) && is(R == typeof(takeExactly(R,
 1)))

 can be written in a more compact way as

 is(typeof(takeExactly(R, 1)) == R)
Technically, no: That was my first try, and as mentioned in the first reply, this returns true when the types of takeExactly and R are equal comparable, but does not make sure they are the actually the same types. ...
I assume you messed up the parentheses. is(typeof(takeExactly(R, 1) == R)) // test for equal-comparable is(typeof(takeExactly(R, 1)) == R) // test for type identity alias float flt; static assert(is(typeof(1==flt))); static assert(!is(typeof(1)==flt));
Yes sorry. I miss read that. Kind of weird though, could you explain why: struct S{}; is(typeof(takeExactly(S, 1)) == S) //false is(S == typeof(takeExactly(S, 1))) //Error: template std.range.takeExactly does not match any function template declaration I was under the understanding that == was a commutative operation. Not the case in an is block?
It is special syntax, not an == operator. is-expressions suppress errors in the first argument only.
Sep 26 2012
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/26/12 9:50 AM, monarch_dodra wrote:
 struct S{};

 is(typeof(takeExactly(S, 1)) == S) //false
 is(S == typeof(takeExactly(S, 1))) //Error: template
 std.range.takeExactly does not match any function template declaration
Neither should work. The expression should be takeExactly(S.init, 1). Andrei
Sep 26 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 09/26/2012 05:08 PM, Andrei Alexandrescu wrote:
 On 9/26/12 9:50 AM, monarch_dodra wrote:
 struct S{};

 is(typeof(takeExactly(S, 1)) == S) //false
 is(S == typeof(takeExactly(S, 1))) //Error: template
 std.range.takeExactly does not match any function template declaration
Neither should work. The expression should be takeExactly(S.init, 1). Andrei
http://d.puremagic.com/issues/show_bug.cgi?id=8220 https://github.com/D-Programming-Language/dmd/pull/1007
Sep 26 2012
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
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.
Sep 23 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Sep 23 2012
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
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) } -------
Sep 23 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
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
Sep 23 2012