New syntax proposal for template type parameter contraints
Idan Arye via Digitalmars-d
digitalmars-d at puremagic.com
Fri May 16 18:28:48 PDT 2014
On Saturday, 17 May 2014 at 00:42:35 UTC, Phil Lavoie wrote:
> On Friday, 16 May 2014 at 23:14:13 UTC, Idan Arye wrote:
>> On Friday, 16 May 2014 at 20:31:40 UTC, Phil Lavoie wrote:
>> The main problem is that `myTemplateFunction`'s signature
>> makes it look like it's a concrete function, when in fact it's
>> a template.
>
> True. To me that is not a big issue though. It can lead to some
> surprises I see your point but I would be ok with that.
When I see such a signature as `void myTemplateFunction(
InputRange!int r ) {` I'm automatically assuming I can do things
like `void function(InputRange!int) foo = &myTemplateFunction;`,
but in our case I can't since it's a template. Also, since it's a
template, certain instantiations might cause it to crash. We have
come to expect such things from templates, but here we don't
expect a template.
Also, I'm not very familiar with the internals of the parser, but
I'm pretty sure that not being able to tell if a declaration is a
template or not based on it's signature will cause a serious
headache...
>> Another problem is that we now have to have an argument if we
>> want to pass a template parameter, which is a serious
>> limitation.
>
> Not sure I get what you mean. I didn't mean for the old syntax
> to be abandonned if that makes sense, just to add some sugar to
> the existing one.
void myTemplateFunction(){
InputRange!int r;
r.doSomething();
}
When you call `myTemplateFunction`, how do you tell it which
concrete type that implements `InputRange` to use?
Also:
void myTemplateFunction(InputRange!int a, InputRange!int
b){...
Must `a` and `b` share the same type, or can they have two
different types as long as the two types fulfill `InputRange!int`?
>> How about if instead these constraint could be used in `is`
>> expressions like type specializations?
>>
>> void myTemplateFunction(T)(T r) if(is(T : InputRange!int)) {
>> foreach(elt; r) { ... }
>> }
>>
>> True, the syntax is less elegant, but it's more flexible, you
>> can easily tell that it's a template, and you can use the same
>> syntax in static branching.
>>
>
> It's interesting. But would it warrant a change from the usual
> syntax, which would probably be:
>
> void myTemplateFunction(T)(T r) if( isInputRange!(T, int)) {
> foreach(elt; r) { ... }
> }
Not as nearly as different from your proposal!
At any rate, this syntax will not be used THAT much. We can
create a wrapper template in Phobos that encapsulates any type
that follows a constraint to create a concrete type that
delegates ONLY the constraints' methods to the real
struct/object. That way we can create concrete functions:
void
myTemplateFunction(InterfaceTemplateWrapper!(InputRange!int) r)
{...
That way we can make sure `myTemplateFunction` doesn't use any
other methods of `r` that don't appear in `InputRange!int` but
happen to be in the all concrete types we have send to the
function.
> Hmm do you mean like a struct "implementing" an interface?
>
> struct MagicRange: InputRange {
> ...
> }
>
> Where it's not an actual interface but the compiler would check
> it against the constraint(s). Which would be nice to make sure
> that a type follows a given interface, although, as soon as it
> is used as an InputRange you would know.
Assuming it is used as an InputRange at some template that gets
instantiated. If you are writing a library there is a chance that
a lot of your code is templates that only get instantiated when
the library is used.
Yes, you should have unit tests, but having the type system check
things is better.
>> BTW - I'm don't think we need a new keyword for this - we can
>> use `interface template` instead.
>
> Love it! Would "template interface" make more sense?
In `mixin template` the word "template" comes second. Consistency
is always good, and I see no benefit from breaking it here.
More information about the Digitalmars-d
mailing list