www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - writeln calls postblits constructor four times before print

reply "FreeSlave" <freeslave93 gmail.com> writes:
Code:

module vector;

import std.stdio;
import std.traits;

struct SVector(size_t dim, T = float)
{
private:
     T[dim] _arr;
public:
     alias dim dimension;
     alias dim size;

     this(this)
     {
         debug(SVector)
             writeln("postblit constructor");
     }

     this(const T[dim] arr)
     {
         debug(SVector)
             writeln("constructor from static array");
         _arr = arr;
     }

     this(ref const T[dim] arr)
     {
         debug(SVector)
             writeln("constructor from ref static array");
         _arr = arr;
     }

     this(const(T)[] arr)
     {
         debug(SVector)
             writeln("constructor from slice");
         assert(arr.length == dim);
         _arr = arr;
     }

     ref SVector opAssign(const SVector other)
     {
         debug(SVector)
             writeln("assign other vector");
         _arr = other._arr;
         return this;
     }

     ref SVector opAssign(ref const SVector other)
     {
         debug(SVector)
             writeln("assign other ref vector");
         _arr = other._arr;
         return this;
     }

     ref SVector opAssign(const T[dim] arr)
     {
         debug(SVector)
             writeln("assign static array");
         _arr = arr;
         return this;
     }

     ref SVector opAssign(ref const T[dim] arr)
     {
         debug(SVector)
             writeln("assign ref static array");
         _arr = arr;
         return this;
     }

     ref SVector opAssign(const(T)[] arr)
     {
         debug(SVector)
             writeln("assign dynamic array");
         assert(arr.length == dim);
         _arr = arr;
         return this;
     }

     T[] opSlice()
     {
         return _arr[];
     }
     T[] opSlice(size_t begin, size_t end)
     {
         return _arr[begin..end];
     }

     const(T)[] opSlice() const
     {
         return _arr[];
     }
     const(T)[] opSlice(size_t begin, size_t end) const
     {
         return _arr[begin..end];
     }

     T opIndex(size_t i) const
     {
         return _arr[i];
     }
     T opIndexAssign(const(T) value, size_t i)
     {
         return _arr[i] = value;
     }

     size_t opDollar() const
     {
         return dim;
     }
}

unittest
{
     alias float scalar;
     alias SVector!(3, scalar) vec;

     vec v = [1,2,3];

     writeln(v);
}

int main()
{
     return 0;
}

This type has simple postblit constructor, but what if it needs 
to allocate memory? Simple example is this._arr = _arr.dup if we 
would use dynamic array. We have really big overhead here.

By the way, why does writeln able to print this struct? It has no 
toString() method and its data is private. How does writeln have 
access to it?
Dec 11 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
FreeSlave:

 By the way, why does writeln able to print this struct? It has 
 no toString() method and its data is private. How does writeln 
 have access to it?
writeln is able to print structs that don't have a toString, this is very handy in most cases. When you don't want it, there's disable, this doesn't link: struct Foo { int x; //string toString() { return "x"; } disable string toString(); } void main() { import std.stdio; Foo f = Foo(10); writeln(f); } In theory this should be caught by writefln constraint before the linker. Probably I can turn this into a small enhancement request. Bye, bearophile
Dec 11 2013
parent "bearophile" <bearophileHUGS lycos.com> writes:
 In theory this should be caught by writefln constraint before 
 the linker. Probably I can turn this into a small enhancement 
 request.
On the other hand if you care about this it's better for you to open the ER. Bye, bearophile
Dec 11 2013