Passing struct to function

Steven Schveighoffer schveiguy at yahoo.com
Wed Jun 13 17:37:44 UTC 2018


On 6/13/18 1:08 PM, Michał wrote:
> On Wednesday, 13 June 2018 at 16:40:51 UTC, Steven Schveighoffer wrote:
>> On 6/13/18 10:43 AM, Michał wrote:
>>> When I pass my struct to function something is going wrong. I don't 
>>> know how to fix it.
>>>
>>> Code:
>>> import std.stdio;
>>>
>>>
>>> void print(ref Vector v, string s){
>>>          writefln("%s==%s    %s", &v.x, v.ptr, s);
>>> }
>>>
>>> struct Vector {
>>>      int x;
>>>      int* ptr;
>>>
>>>      this(this) {
>>>          ptr = &x;
>>>          print(this, "postblit");
>>>      }
>>> }
>>>
>>> void someFunc(Vector t) {
>>>      print(t, "in someFunc");
>>> }
>>>
>>> void main() {
>>>      auto tmpA = Vector();
>>>      tmpA.ptr = &tmpA.x;
>>>      print(tmpA, "start");
>>>
>>>      someFunc(tmpA);
>>> }
>>>
>>>
>>> Result on my machine:
>>> 7FFF7D70BC00==7FFF7D70BC00    start
>>> 7FFF7D70BBF0==7FFF7D70BBF0    postblit
>>> 7FFF7D70BBD0==7FFF7D70BBF0    in someFunc
>>>
>>> In the last line pointers are not matching. I thought that postblit 
>>> will do the thing but it is not the case. How to make 'ptr' to be 
>>> null or '&this.x' all the time?
>>
>> D allows moving any struct instance without calling postblit, as long 
>> as the original is no longer used.
>>
>> The optimizer is likely seeing here that the memory can be copied 
>> without calling postblit, because nobody is using tmpA after the call.
>>
>> In general, you should NOT store an internal pointer in a struct, 
>> unless you allocate it on the heap.
>>
>> -Steve
> 
> 
> I need internal pointer because I want to implement vector(like in C++) 
> with 'small vector optimization', when i have internal pointer it is 
> very easy and functions like 'add' don't have additional checks.
> 
> If storing internal pointers is forbidden do you know some way to 
> implement 'small vector optimization' without additional checks in 'add' 
> function?

Hm... the only way to do it in D is to provide a function that checks 
whether the small vector optimization is in play, and return a 
pointer/slice to itself.

With D it is possible to alias the getter function that provides the 
actual data to allow code to look nicer.

For example (crude example):

struct Vector(T)
{
    bool svo; // small vector optimization
    union
    {
       T[4] local;
       T[] heap;
    }
    inout(T)[] get() inout { return svo ? local[], heap; }
    alias get this;
    ... // implement specialized append, concat operators, etc.
}

Now, you can use Vector as if it were an array, and it just works.

-Steve


More information about the Digitalmars-d-learn mailing list