Using constructors with arrays in D - arrays

How do you call constructors when allocating an array with new?
For example, in the following code how would I call the constructor for each instantiation of A, initialising b to 5 for all 10 elements?
void main() {
A[] a = new A[10];
}
class A {
int b;
this(int init) {
b = init;
}
}
I'm guessing it's not possible, but I can hope...

a simple loop should do (and it's the most readable)
foreach(ref el;a){
el=new A(5);
}
or you can use the array initializer:
A[] a=[new A(5),new A(5),new A(5),new A(5),new A(5),
new A(5),new A(5),new A(5),new A(5),new A(5)];

If you're dealing with a value type, you can use std.array.replicate.
auto a = replicate([5], 50);
would create an int[] of length 50 where each element is 5. You can do the same with a reference type, but all of the elements are going to refer to the same object.
auto a = replicate([new A(5)], 50);
will only call A's constructor once, and you'll end up with an A[] where all of the elements refer to the same object. If you want them to refer to separate objects, you're either going to have to set each element individually
auto a = new A[](50);
foreach(ref e; a)
e = new A(5);
or initialize the whole array with a literal
auto a = [new A(5), new A(5), new A(5)];
But that clearly will only work for relatively small arrays.

If you really want to do it in one line, you could write a macro to do it for you. I've borrowed code for the actual initialisation from the other answers.
template allocate(T) {
T[] allocate(int size, int arg) {
T[] result = new T[size];
foreach(ref el; result)
el=new T(arg);
return result;
}
}
Then you can allocate an entire array of 10 elements at once with:
A[] a = allocate!(A)(10, 5);
Of course this has fixed constructor arguments, but you could probably do something with variadic arguments to the template and some mixins to generate the correct constructor call.

Related

Conflicting declaration for 2d array in c++?

I came across a problem where i need to declare a 2D array dynamically.
The number of rows were known(i.e 2) while the number of columns are to taken as input.
I used this technique :
cin>>size;
int **outer = new int*[2];
int outer[0] = new int[size];
int outer [1] = new int[size];
But this gave an error : conflicting declaration 'int outer [0]'
Than i fixed the problem by changing my code to :
cin>>size; // size of the column
int **outer = new int*[2];
for(int i=0;i<2;i++)
outer[i] = new int[size];
So, i want to know why can't i declare 2D array like as that of 1st , bcz i am declaring it after i have declared and defined the size.
With
int outer[0] = ...;
you define a completely new variable named outer, as an array of zero elements.
Plain assignment seems to be what you want:
outer[0] = new int[size];
outer[1] = new int[size];
And I really recommend you don't use your own manual memory and pointer handling. First fix would be to realize that outer doesn't need to be a pointer but an array, as in
int* outer[2] = {
new int[size],
new int[size]
};
Then eliminating pointers altogether using std::vector you could do it as
std::vector<int> outer[2] = {
std::vector<int>(size),
std::vector<int>(size)
};
You should also consider replacing the C-style array with std::array:
std::array<std::vector<int>, 2> outer = {
std::vector<int>(size),
std::vector<int>(size)
};

Design of C++ dynamic arrays

I am in the process of designing some classes for dynamic arrays (something like a std::vector). The reason I don't want to use std::vector is because my C++ programs are often used as a library called from C/C++/Fortran/Delphi and therefore takes arrays input as a pointer. For security reasons, a std::vector can't steal a pointer at construction time. My Array1D can work as a std::vector but can also be constructed with a pointer. Unfortunately Visual Studio 2013 seems to be worried about my design. Before presenting the problem, I need to explain this design.
Here is the layout of my class
template <typename T>
class Array1D {
private:
T* data_;
T* size_; // No stored as an int for optimisation purposes
bool owner_;
public:
Array1D(int n) {
data_ = new T[n];
size_ = data_ + n;
owner_ = true;
}
Array1D(T* data, int n) {
data_ = data;
size_ = data + n;
owner_ = false;
}
...
};
Most of the time, it works as a std::vector and owner_ is set to true. One can also construct an Array1D from a pointer, and this time owner_ is set to false. In this case, some operations such as resizing are not allowed (through an assert). Copy constructor and assignment for the array A are designed as:
Array1D(const Array1D& B) : Deep copy of B into A. After construction, A owns its memory.
Array1D(Array1D&& B) : Move operation in all cases. After construction, the ownership status of A is the same as B.
operator=(const Array1D& B) : Deep copy of B into A. If A does not owns its memory, an assert is there to check that A and B have the same size. The assignment does not change the ownership status of A.
operator=(Array1D&& B) : Move operation if A and B owns their memory. Otherwise, we do a deep copy, and the size are checked with an assert if A does not own its memory. The assignment does not change the ownership status of A.
I have applied the same idea to my 2 dimensional array whose elements are stored in row-major order
template <typename T>
class Array2D {
private:
T* data_;
T* size_[2];
bool owner_;
public:
Array2D(int n, int p) {
data_ = new T[n];
size_[0] = data_ + n;
size_[1] = data_ + p;
owner_ = true;
}
Array1D(T* data, int n, int p) {
data_ = data;
size_[0] = data + n;
size_[1] = data + p;
owner_ = false;
}
...
Array1D<T> operator()(int i) {
Array1D<T> row(data_ + i * nb_columns(), nb_columns());
return row;
}
...
int nb_columns() const {
return static_cast<int>(size_[1] - data_);
}
};
The Array1D returned by operator()(int i) does not own its memory and contains a pointer to the ith-row owned by the Array2D object. Is is useful in the following kind of code
sort(Array1D<T>& A); // A function that sorts array in place
Array2D<double> matrix(5, 100); // Construct an array of 5 rows and 100 columns
... // Fill the array
sort(matrix(3)) // Sort the 4th row
Those "temporary views" for rows of an 2 dimensional arrays are quite useful but I prefer to limit them to temporary objects to limit aliasing.
Unfortunately, using Visual Studio 2013, I get the following warning from the IDE for the line sort(matrix(3)): "Options for binding r-value to l-value reference is non-standard Microsoft C++ extension". I understand that matrix(3) is an object that lives temporarly and modifying it through a sort looks strange. But, as it is a "view", modifying it modifies the memory owned by matrix and is useful.
So my questions are the following:
Is what I am doing valid C++? (modifying a temporary value)
Is there a flaw in this design?
PS: The full code is available on Github.
Is what I am doing valid C++? (modifying a temporary value)
It's not. Non-const lvalue references cannot bind to temporary objects:
http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
Is there a flaw in this design?
You are modifying the contents that are wrapped in an object. Since you need to have an lvalue, it would simply be fixed by having an intermediate variable:
auto m_temp_lvalue = matrix(3); // get the 4th row
sort(m_temp_lvalue); // sort the 4th row
I hope it helps.

Converting a List to an old-school array of doubles

I am working with a DLL for some hardware that requires old-school arrays as arguments. I'm using Visual C++ Express 2010.
For example, it might have
bool DLLFunction(double* array1, double* array2, int array1length, int array2length);
I'm trying to isolate all that inside a singleton class, so that outside the singleton everything uses Lists and Arrays. That means I have a bunch of wrapper functions that take Lists and then convert them to double[] to pass to the DLL.
As such, I've made the following helper function to convert a List to a double[]. The problem is that the pointer-to-double comes out of the function as undefined.
bool MySingleton::AdaptList(List<double> ^myList, double *myDouble) {
if(myDouble)
delete(myDouble);
myDouble = new double[myList->Count];
for(int k=0; k<myList->Count; k++) {
myDouble[k] = myList[k];
}
return true;
} // AdaptList from List to Double*
In my code, I do something like:
double *oldschool;
List<double>^ myList;
myList = gcnew List<double>;
// a bunch of myList.Add( ) calls to add the data
bool success = AdaptList(myList, oldschool);
// eventually, delete oldschool
Using the debugger, inside the AdaptList function, oldschool holds exactly what it needs. When AdaptList returns control, oldschool shows undefined.
Why did it go out of scope?
Thanks!
Whenever you need an unmanaged pointer to an array it is always worth considering if you can get one from pin_ptr<>. It will temporarily pin the array in memory so it cannot be moved while the native code is using it. Something like this:
List<double>^ list = gcnew List<double>;
//...
pin_ptr<double> p = &list->ToArray()[0];
NativeFunctionTakesDoublePointer(p);
You can't use it if the NativeFunction() stores the pointer since the array will be unpinned when the p variable goes out of scope.
You need to either pass a double pointer to the MySingleton::AdaptList member function:
bool MySingleton::AdaptList(List<double> ^myList, double **myDouble) {
if(*myDouble) delete(*myDouble);
*myDouble = new double[myList->Count];
for(int k = 0; k < myList->Count; ++k) (*myDouble)[k] = myList[k];
return true;
} // AdaptList from List to Double*
or a reference to a pointer:
bool MySingleton::AdaptList(List<double> ^myList, double *&myDouble) {
if(myDouble) delete myDouble;
myDouble = new double[myList->Count];
for(int k = 0; k < myList->Count; ++k) myDouble[k] = myList[k];
return true;
} // AdaptList from List to Double*
Reason: You were passing the 'myDouble' pointer by value and not by reference in member function bool MySingleton::AdaptList.

Why is &array != &array[0]?

In C:
int a[10];
printf("%p\n", a);
printf("%p\n", &a[0]);
Yields:
0x7fff5606c600
0x7fff5606c600
Which is what I expect. Now, in D, I'm trying this (obviously no use case, just fooling around):
int[] slice = [...];
writeln(&slice);
writeln(&slice[0]);
Yields:
7FFF51600360
10E6E9FE0
Why the difference? Looks like a completely different memory segment. (Though it just occurred to me that perhaps arrays in D aren't just adjacently allocated ints?)
in D an array is essentially a struct with a pointer and a length field and is treated as such
to get the address to the first element you can query the ptr field
It is simple - dynamic D arrays are not the same as C arrays. Dynamic D arrays hold the length of the array, while C arrays do not. As such dynamic D arrays do not rely on a NULL to mark the end of the array. As Adam points out in his comment, static D arrays behave the same as C arrays.
import std.stdio;
int main() {
// static array
int[10] sarr;
writeln(sarr.length);
writeln(&sarr);
writeln(&sarr[0]);
// dynamic array
int[] darr = [1, 2, 3];
writeln(darr.length);
writeln(&darr);
writeln(&darr[0]);
// These are all the same
writeln(darr.ptr);
writeln(cast(void*) darr);
writeln(&darr[0]);
return 0;
}
(DPaste link: http://dpaste.dzfl.pl/f708d945)
Because "array" used by itself resolves to a pointer to the array, this allows you to treat pointer-to-type and array-of-type somewhat similarly when using structs.
int[] slice = [...];
writeln((cast(void*) slice);
writeln(&slice[0]);
should give you what you want.
Inherited from "C" http://c-faq.com/aryptr/aryptrequiv.html
int[] slice = [...];
int* ptr = &slice[0];
writeln(cast(void*) slice);
writeln(&slice[0]);
// value access
writeln(slice[0]);
writeln(*ptr);
writeln(ptr[0]);

D dynamic array initialization, stride and the index operation

Sorry, this became a 3-fold question regarding arrays
I think (dynamic) arrays are truly powerful in D, but the following has been bothering me for a while:
In C++ I could easily allocate an array with designated values, but in D I haven't found a way to do so. Surely the following is no problem:
int[] a = new int[N];
a[] = a0;
But it looks inefficient, since line one will initialize with 0, and like 2 with a0. Could something similar to the following be done in D?
int[] a = new int(a0)[N]; // illegal
Another efficiency matter I have when using stride in std.range:
import std.stdio;
import std.range;
struct S
{
int x;
this(this)
{
writeln("copy ", x);
}
}
void f(S[] s)
{
}
int main()
{
S[] s = new S[10];
foreach (i, ref v; s)
{
v.x = i;
}
f(stride(s, 3)); // error
return 0;
}
Surely I was naive thinking I could simply use stride to create a new array without copying it's elements? There is no way to do so in D, right?
So I went and simulated as if the array was as stride would return, and implemented f as:
f(s, 3);
void f(S[] s, uint stride)
{
ref S get(uint i)
{
assert (i * stride < s.length);
return s[i * stride];
}
for (uint x ... )
{
get(x) = ...;
}
}
Would there be a way to instead write get(x) using the index operator get[x]? This way I could statically mixin / include the striding get function and keep the rest of the function similar. I'd be interested in the approach taken, since a local struct is not allowed to access function scope variables (why not?).
But it looks inefficient, since line one will initialize with 0, and like 2 with a0. Could something similar to the following be done in D?
Use std.array.uninitializedArray
S[] s = uninitializedArray!(S[])(N);
s[] = a0;
Surely I was naive thinking I could simply use stride to create a new array without copying it's elements? There is no way to do so in D, right?
Your function f has an S[] as an argument, which is different from what stride returns. The D way to solve this is to make your f function accept any range by making it a template:
void f(Range)(Range s)
{
foreach (item; s)
// use item
}
S[] s = new S[10];
f(s); // works
f(stride(s, 3)); // works too
Alternatively you can copy the array:
f(array(stride(s, 3)));
But you probably want to avoid copying the entire array if it is large.
Would there be a way to instead write get(x) using the index operator get[x]? This way I could statically mixin / include the striding get function and keep the rest of the function similar. I'd be interested in the approach taken, since a local struct is not allowed to access function scope variables (why not?).
You can overload the indexing operator in your own struct.
struct StrideArray
{
this(S[] s, uint stride) { m_array = s; m_stride = stride; }
S opIndex(size_t i) { return s[i * m_stride]; }
void opIndexAssign(size_t i, S value) { s[i * m_stride] = value; }
private S[] m_array;
private uint m_stride;
}
This is (kind of) the way the actual stride function works. I'd recommend reading up on Ranges.
you can duplicate (create a copy of) an array with .dup (this will also work with slices) or you can set the elements with the array initializer
int[] a=a0.dup;
int[] b=[e1,e2,e3];
you can make the f generic (stride() returns a struct that you can iterate over, not an array)
void f(Z)(Z s)if(isInputRange!Z){
foreach(elem;s){
//...
}
}
remember that arrays are essentially structs with a pointer field to some memory block and a size field

Resources