Re: Remove elements without losing capacity

2022-10-04 Thread Riccardo M via Digitalmars-d-learn

On Tuesday, 4 October 2022 at 18:18:41 UTC, Ali Çehreli wrote:

On 10/4/22 10:59, Riccardo M wrote:

> The inherent reason for `remove` to cancel previous capacity
and
> requiring new allocations is exactly to prevent overwriting
data that
> could be owned by something else?

Yes.

A related topic is how the "end slice" never loses that 
capacity:


void main() {
auto a = [ 1, 2 ];
auto b = a;

assert(a.capacity != 0);
assert(b.capacity != 0);

b.length--;
assert(b.capacity == 0);
assert(a.capacity != 0);// <-- Preserved
}

Aside: .capacity is an expensive operation that requires some 
levels of table lookups in the druntime. A data structure would 
benefit a lot if it kept its own capacity as a member variable.


Ali


Wonderful. Thanks for the insight,


Re: Remove elements without losing capacity

2022-10-04 Thread Riccardo M via Digitalmars-d-learn
On Tuesday, 4 October 2022 at 15:42:21 UTC, Steven Schveighoffer 
wrote:

Yes, you use `assumeSafeAppend`:

```d
arr.length--;
arr.assumeSafeAppend;
assert(arr.capacity != 0);
```

Now, I want to clarify that you should only use this if you are 
sure you are done with the data you removed at the end, as it 
will get overwritten upon more appends to the array.


[...]


Thanks! I can use the unstable `remove` and then restore the 
original capacity with `assumeSafeAppend` in case data can be 
safely overwritten.


The inherent reason for `remove` to cancel previous capacity and 
requiring new allocations is exactly to prevent overwriting data 
that could be owned by something else?


Re: Interfacing with basic C++ class

2022-10-02 Thread Riccardo M via Digitalmars-d-learn

On Friday, 30 September 2022 at 22:56:06 UTC, Ogi wrote:
On Thursday, 29 September 2022 at 12:49:06 UTC, Riccardo M 
wrote:
When interfacing to C++, disregard the keyword and look at the 
implementation instead. If all its member functions are 
non-virtual, map it to struct. Otherwise map it to class. If it 
defines at least one pure virtual member function, map it to 
abstract class. If all its member functions are either pure 
virtual or non-virtual and it contains no fields, map it to 
interface. Sounds complicated? Well, that’s because C++ is 
complicated.


Ok, in layman terms, is it correct to say that I should match the 
underlining structure of the object (e.g in terms of vtbl) so 
that C++ side and D side can work with each other correctly?


In C++, member functions defined inside its class are called 
*inline* member functions. In contrast to normal functions 
which must be defined once and only once in your program, 
inline functions must be defined in every translation unit that 
uses them. Let’s replicate your linking error in C++:


Well, I didn't know the implications of inlining member 
functions: basically when a member function is inlined, it has no 
linkage so I am pretty much done with using D in such case. While 
in C++ you can import the header and call the member function 
anyway.
The only solution would be reimplementing the offending function 
on D side.


Re: Interfacing with basic C++ class

2022-09-29 Thread Riccardo M via Digitalmars-d-learn

On Thursday, 29 September 2022 at 11:13:15 UTC, Ogi wrote:
Ali is correct. However, you don’t have to change anything on 
the C++ side, just map C++ class to D struct:

[...]


Thanks, this works perfectly.
Now i see that I can even instantiate directly from D, calling 
the default ctor, calling the custom ctor or even overriding the 
custom ctor in D (the fact that ctors could be called, in 
contrast with docs, was in fact hinted at DConf 2022 as suggested 
by Ali).


So it turns out that D's structs are a much better match for 
C++'s classes in this case. But why is this? Can you elaborate? 
It must have to do with the fact that D structs are passed by 
value?


Now this D code runs as expected:
```
// D
extern(C++, class) {
struct MyClass {
public: 
int field;
this(int a);
int add(int asd);
}

MyClass* instantiate(int asd);
}

void main()
{
import std : writeln;

	auto myclass = instantiate(100); //actually, instantiation 
through C++ is not required any longer

assert(myclass.field == 100);

auto myclass2 = new MyClass;
assert(myclass2.field == 0);

auto myclass3 = new MyClass(50);
assert(myclass3.field == 50);

assert(myclass3.add(40) == 90);
}
```
However the 'add' function only links correctly if C++ has the 
function body defined outside of its class.

```
// C++
int MyClass::add(int asd) {
return field + asd;
}
```
If the function is defined inside its class, it is an undefined 
reference at link time. Once again I ask for clarifications and 
workarounds, if possible.


Thanks


Re: Interfacing with basic C++ class

2022-09-29 Thread Riccardo M via Digitalmars-d-learn
On Wednesday, 28 September 2022 at 20:41:13 UTC, Ali Çehreli 
wrote:

[...]

Ali


Thank you, that is perfect!

However that begs the following observation: it would be rather 
hard to link to a C++ library only by means of 'extern (C++)' if 
one should slightly rearrange C++ code as well. This sounds like 
it is rather obvious to the community, actually, but I am a 
recent addition to D language :)


Do you know that this is documented somewhere? The examples in 
the official docs are rather limited, maybe studying a github 
with previous work might help.


Cheers


Interfacing with basic C++ class

2022-09-28 Thread Riccardo M via Digitalmars-d-learn
I think I am stuck in the easiest of the issues and yet it seems 
I cannot get around this.

I have a C++ file:
```
class MyClass {
public:
int field;
MyClass(int a) : field(a) {}

int add(int asd) {
return asd + 1;
}
};

MyClass* instantiate(int asd) {
return new MyClass(asd);
}
```
and a D file:
```
extern(C++) {
class MyClass {
public: 
int field;
@disable this();
final int add(int asd);
}

MyClass instantiate(int asd);
}

void main()
{
import std : writeln;
auto myclass = instantiate(100);
writeln(myclass.field);
}
```
This is a very simplified version of the dlang official example 
of interfacing with C++ classes.


When I compile, I can't correctly read 'field'. What I do:
```
g++ -c cpp.cpp
dmd app.d cpp.o -L-lstdc++
./app
```
What I get:
```
0
```
Instead of the expected 100.

Care to help me understand what am I doing wrong?

Side question: it seems that I need to declare every class method 
as "final" otherwise I get  undefined references during linking. 
Is this expected behaviour?


Thanks