Thread overview | ||||||
---|---|---|---|---|---|---|
|
November 05, 2014 New reference type designed to handle templates better | ||||
---|---|---|---|---|
| ||||
I've been thinking about how to handle templates that have typically been using the 'ref' parameter attribute because they modify the parameter. For example, the put/doPut functions in std.range use the 'ref' attribute for the output range, but in many cases the parameter doesn't need to be a reference type and the overhead that comes with it. One idea I had is to have a different type of function argument attribute as opposed to "ref". A "ref" parameter is passed by reference. Under the hood, a reference parameter is equivalent to a pointer to the variable. Then the function is free to modify the caller's "version" of the variable. This new type of function parameter, let's call it "pref", would instead care about what the variable is "pointing to" instead of the variable itself. In some cases this means modifying the caller's version of the variable and in some cases it does not. For example, if a basic value type like int was passed in, the variable isn't pointing to anything so a pointer to the variable itself would be passed in, but if an int* was passed in, then the int* would be passed by value. I've included a table of common types and how "pref" would differ from "ref". pref: modifying the data the variable is pointing to. This means that if the variable is itself a pointer, then the function won't modify the pointer but instead modify what it's pointing to. BasicDataType (BDT) is bool, all integer types, all float types, and all char types Type | ref | pref | why -------------------------------------------- BDT | BDT* | BDT* | A BDT is not a pointer, so pref must | modify the variable itself which you can | say is pointing to a location in memory BDT* | BDT** | BDT* | A BDT* is already a pointer, pref will | modify the memory BDT is pointing to BDT[] | BDT[]* | BDT[]* or BDT[] | An argument can be made for both, | if the function is modifying the contents | of the array (maybe writing data to it), | then the function might need some way of | returning how much data was written so | it might want to modify the given array | to indicate it has changed. struct | struct* | struct* | A struct variable is not a pointer, so | pref is a reference type for the struct struct* | struct** | struct* | A struct pointer is already a pointer class | class* | class | A class is already a pointer function | function* | function | A function is a pointer to code, a | function is usually used to modify data so pref treats the function as what is modifying the data. delegate | delegate* | delegate | Same as reason for function Note: A pref modifer to a type that is a pointer to any of these types will not do anything to the type |
November 05, 2014 Re: New reference type designed to handle templates better | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Marler | On Wednesday, 5 November 2014 at 19:27:59 UTC, Jonathan Marler
wrote:
> I've been thinking about how to handle templates that have typically been using the 'ref' parameter attribute because they modify the parameter. For example, the put/doPut functions in std.range use the 'ref' attribute for the output range, but in many cases the parameter doesn't need to be a reference type and the overhead that comes with it.
>
> One idea I had is to have a different type of function argument attribute as opposed to "ref".
>
> A "ref" parameter is passed by reference. Under the hood, a reference parameter is equivalent to a pointer to the variable.
> Then the function is free to modify the caller's "version" of the variable. This new type of function parameter, let's call it "pref", would instead care about what the variable is "pointing to" instead of the variable itself. In some cases this means modifying the caller's version of the variable and in some cases it does not. For example, if a basic value type like int was passed in, the variable isn't pointing to anything so a pointer to the variable itself would be passed in, but if an int* was passed in, then the int* would be passed by value. I've included a table of common types and how "pref" would differ from "ref".
>
> pref: modifying the data the variable is pointing to. This means that if the variable is itself a pointer, then the function won't modify the pointer but instead modify what it's pointing to.
>
> BasicDataType (BDT) is bool, all integer types, all float types, and all char types
>
> Type | ref | pref | why
> --------------------------------------------
> BDT | BDT* | BDT* | A BDT is not a pointer, so pref must
> | modify the variable itself which you can
> | say is pointing to a location in memory
> BDT* | BDT** | BDT* | A BDT* is already a pointer, pref will
> | modify the memory BDT is pointing to
> BDT[] | BDT[]* | BDT[]* or BDT[] | An argument can be made for both,
> | if the function is modifying the contents
> | of the array (maybe writing data to it),
> | then the function might need some way of
> | returning how much data was written so
> | it might want to modify the given array
> | to indicate it has changed.
> struct | struct* | struct* | A struct variable is not a pointer, so
> | pref is a reference type for the struct
> struct* | struct** | struct* | A struct pointer is already a pointer
> class | class* | class | A class is already a pointer
> function | function* | function | A function is a pointer to code, a
> | function is usually used to modify data so pref treats the function as what is modifying the data.
> delegate | delegate* | delegate | Same as reason for function
>
> Note: A pref modifer to a type that is a pointer to any of these types will not do anything to the type
Not sure what you mean, but can't you just def a pointer when
passing to ref function
----
void mycalle(ref int i){
}
int mycaller(){
int* var=new int;
mycalle(*var);
}
----
|
November 07, 2014 Re: New reference type designed to handle templates better | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Marler | On Wednesday, 5 November 2014 at 19:27:59 UTC, Jonathan Marler wrote: I haven't gotten any responses on this so I'll try one more time. The proposal is to add a new function parameter attribute, called "pref" for now. Here's the difference: ref : modifies the caller's variable pref: modifies the CONTENTS of the caller's variable Here's some examples. These are all exactly the same: void modify(int* x) { *x = 3; } void modify(ref int x) { x = 3; } void modify(pref int x) { x = 3; } void modify(pref int* x) { x = 3; } These are not the same void modify(class c) { c.myfield = 3; } void modify(ref class c) { c.myfield = 3; } // NOT EQUIVALENT // the ref parameter means the function can modify which // instance the callers variable is actually pointing to. // This adds an unnecessary level on indirection. void modify(pref class c) { c.myfield = 3; } Keep in mind, the pref attribute isn't very useful for Non-Template functions because you can just use 'ref' or not. However, in a template, the 'pref' attribute will select whether the parameter is pass by reference or pass by value based on the type. |
November 07, 2014 Re: New reference type designed to handle templates better | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Marler | On Friday, 7 November 2014 at 19:42:58 UTC, Jonathan Marler wrote: > On Wednesday, 5 November 2014 at 19:27:59 UTC, Jonathan Marler wrote: > > I haven't gotten any responses on this so I'll try one more time. The proposal is to add a new function parameter attribute, called "pref" for now. Here's the difference: > > ref : modifies the caller's variable > pref: modifies the CONTENTS of the caller's variable > > Here's some examples. > > These are all exactly the same: > > void modify(int* x) { *x = 3; } > void modify(ref int x) { x = 3; } > void modify(pref int x) { x = 3; } > void modify(pref int* x) { x = 3; } > > These are not the same > > void modify(class c) { c.myfield = 3; } > > void modify(ref class c) { c.myfield = 3; } > // NOT EQUIVALENT > // the ref parameter means the function can modify which > // instance the callers variable is actually pointing to. > // This adds an unnecessary level on indirection. > > void modify(pref class c) { c.myfield = 3; } > > Keep in mind, the pref attribute isn't very useful for Non-Template functions because you can just use 'ref' or not. However, in a template, the 'pref' attribute will select whether the parameter is pass by reference or pass by value based on the type. I think Manu and deadlnix should comment on this - they complained about `ref` here: http://forum.dlang.org/thread/etjuormplgfbomwdrurp@forum.dlang.org?page=5 I agree that this is a real problem - but the solution you propose feels a little ad hoc. It would "solve" this particular problem, but what is the deeper cause for the problems with current ref? |
Copyright © 1999-2021 by the D Language Foundation