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

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.

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

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.

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

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 :/

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.