August 18, 2015 Re: "else if" for template constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Monday, 17 August 2015 at 22:44:15 UTC, anonymous wrote:
> On Monday, 17 August 2015 at 22:32:10 UTC, Idan Arye wrote:
>> On Monday, 17 August 2015 at 21:27:47 UTC, Meta wrote:
> [...]
>>> At that point, couldn't you just use static if inside the body of the template instead of using template constraints?
>>
>> No. Consider this: http://dpaste.dzfl.pl/a014aeba6e68. The having two foo templates is illegal(though it'll only show when you try to instantiate foo), because each of them covers all options for T. When T is neither int nor float, the foo *function* in the first template is not defined, but the *foo* template is still there.
>
> The idea is to have only one template:
>
> template foo(T) {
> static if (is(T == int)) {
> ...
> } else static if (is(T == float)) {
> ...
> } else static if (is(T == char)) {
> ...
> } else static if (is(T == bool)) {
> ...
> }
> }
There is also, as a similar option, the "dispatcher" solution, like for 'std.conv.to'
There is the main template that dispatches the call to the right non templated (or specialized) overload, so that the entry point is just used to redirect the cases that are fundamentaly different.
---
auto foo(T)
{
static if(...) return fooImpl!T(); else
static if(...) return fooImpl!T(); else
//etc
}
private auto fooImpl(T)(){}
private auto fooImpl(T)(){}
private auto fooImpl(T)(){}
---
|
August 19, 2015 Re: "else if" for template constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On 8/17/15 6:44 PM, anonymous wrote:
> On Monday, 17 August 2015 at 22:32:10 UTC, Idan Arye wrote:
>> On Monday, 17 August 2015 at 21:27:47 UTC, Meta wrote:
> [...]
>>> At that point, couldn't you just use static if inside the body of the
>>> template instead of using template constraints?
>>
>> No. Consider this: http://dpaste.dzfl.pl/a014aeba6e68. The having two
>> foo templates is illegal(though it'll only show when you try to
>> instantiate foo), because each of them covers all options for T. When
>> T is neither int nor float, the foo *function* in the first template
>> is not defined, but the *foo* template is still there.
>
> The idea is to have only one template:
>
> template foo(T) {
> static if (is(T == int)) {
> ...
> } else static if (is(T == float)) {
> ...
> } else static if (is(T == char)) {
> ...
> } else static if (is(T == bool)) {
> ...
> }
> }
>
What if there is another foo template that handles double? possibly in another file? There would be a conflict for instantiation.
That is why we use template constraints instead of static if -- the constraint disqualifies the instantiation.
-Steve
|
September 04, 2015 Re: "else if" for template constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Monday, 17 August 2015 at 13:18:43 UTC, Steven Schveighoffer wrote:
> I was just looking at fixing this bug:https://issues.dlang.org/show_bug.cgi?id=14925
>
> [...]
>
> How often are you writing overloaded templates, and you want to say "if it doesn't match anything else, do this"? I'd love to see some form of syntax that brings template constraints in line with tried-and-true if/else statements.
>
> One way to do this is to lexically order the if constraints, and if any of them start with "else", then they are mutually exclusive with the immediately preceding constraint for the same symbol (just like normal else).
>
> So for example, you'd have:
>
> void replaceInPlace(T, Range)(ref T[] array, size_t from, size_t to, Range stuff)
> if(isDynamicArray!Range &&
> is(Unqual!(ElementEncodingType!Range) == T) &&
> !is(T == const T) &&
> !is(T == immutable T))
> { /* version 1 that tries to write into the array directly */ }
>
> void replaceInPlace(T, Range)(ref T[] array, size_t from, size_t to,
> Range stuff)
> else if(is(typeof(replace(array, from, to, stuff))))
> { /* version 2, which simply forwards to replace */ }
>
> looks much better IMO. Can we do something like this? I'm not a compiler guru, so I defer to you experts out there.
>
> -Steve
The biggest problem, I think, is that a template can has multiple 'predicates' to agree to be instantiated, but only some of them can mutually exclusive (the specialization syntax produces mutually exclusive ones, the if-constraints don't).
Thinking about it from this angle, I believe the most flexible and sensible solution would be to support a sort of "early return" from a template. Thus:
template Bar(T) {
static if( is(T == int) || is(T == string) || ... ) {
//stuff
}
else static if( stuff ) {
// other stuff
}
else {
template return; // I know my T took whatever your type was but I actually don't match, please exclude me from your list for this instance...
}
}
template Bar(T) {
static if( is(T == float) || is(T == int[]) || ... ) {
// Bar!float/Bar!(int[]) stuff
}
else static if( OTHER_OTHER_stuff ) {
// other other stuff
}
else {
template return; // I know my T took whatever your type was but I actually don't match, please exclude me from your list for this instance...
}
}
|
September 04, 2015 Re: "else if" for template constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to Enamex | On Friday, 4 September 2015 at 15:52:08 UTC, Enamex wrote:
> The biggest problem, I think, is that a template can has multiple 'predicates' to agree to be instantiated, but only some of them can mutually exclusive (the specialization syntax produces mutually exclusive ones, the if-constraints don't).
> [...]
> template Bar(T) {
> static if( is(T == int) || is(T == string) || ... ) {
> //stuff
> }
> else static if( stuff ) {
> // other stuff
> }
> else {
> template return; // I know my T took whatever your type was but I actually don't match, please exclude me from your list for this instance...
> }
> }
> [...]
On second thought, it wouldn't help as much as I'd thought with overloading problems. What we want is a 'which template has more '&&'ed expressions in its constraint?' which sounds pretty awful. I have no idea how this could work :/
Especially given that D's constraints are way more open than, say, Haskell's, in their checking; though ironically not their declaration/implementation (D is open because it checks for structural conformance of a struct instead of nominative & structural; but it's more restricted because it easily only checks for structure of the type as declared, with no way to attach recognized-to-the-constraint ad-hoc interfaces to a type like Haskell's with type-classes).
|
Copyright © 1999-2021 by the D Language Foundation