Re: Cannot link using DMD nightly

2016-02-28 Thread Matt Elkins via Digitalmars-d-learn
On Sunday, 28 February 2016 at 22:16:39 UTC, Rene Zwanenburg 
wrote:

On Sunday, 28 February 2016 at 19:02:21 UTC, Matt Elkins wrote:

Any suggestions?


I don't know how to fix that error, but 2.070.1 has been 
released and contains a fix for your issue:


http://dlang.org/changelog/2.070.1.html


...I don't know how I missed this. Thanks! It works like a champ, 
including the fix!


Cannot link using DMD nightly

2016-02-28 Thread Matt Elkins via Digitalmars-d-learn
I'm attempting to use the DMD nightly build (because this fix 
matters a lot to my project: 
https://issues.dlang.org/show_bug.cgi?id=15661), but the build 
fails at the link step. Here is my full output:


[output]
"C:\Program Files (x86)\dub\dub.exe" run --force --build debug 
--build-mode separate

Performing "debug" build using dmd for x86.
cake ~master: building configuration "library"...
derelict-util 2.0.4: building configuration "library"...
derelict-ft 1.0.2: building configuration "library"...
derelict-gl3 1.0.18: building configuration "library"...
derelict-glfw3 1.1.1: building configuration "library"...
gl3n 1.3.1: building configuration "library"...
cakegl ~master: building configuration "library"...
common ~master: building configuration "library"...
client ~master: building configuration "application"...
Linking...
OPTLINK (R) for Win32  Release 8.00.17
Copyright (C) Digital Mars 1989-2013  All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
..\cakegl\out\cakegl.lib(utf)
 Error 163: Cannot CVPACK Type 0002
--- errorlevel 1
dmd failed with exit code 1.
[/output]

"cakegl" is one of my libraries used by the application.

I have manually removed every trace of any object file or library 
I could find which was compiled with my previous install of DMD 
(including the third-party ones pulled by dub, such as derelict), 
and am also building with the --force flag; I should note that I 
am using dub for my builds rather than dmd directly.


If I swap back in the released version of DMD it all builds fine. 
This is on 64-bit Windows 7, using the 32-bit DMD nightly build 
downloaded today, Feb 28th.


Any suggestions?


Re: Arrays of noncopyables/Invalid memory operation

2016-02-19 Thread Matt Elkins via Digitalmars-d-learn

On Thursday, 18 February 2016 at 01:14:00 UTC, ZombineDev wrote:
https://issues.dlang.org/show_bug.cgi?id=15661. I suggest 
testing this code again with a newer compiler (see my answer in 
the other thread - 
http://forum.dlang.org/post/omfyqfulgyzbrxlzr...@forum.dlang.org).


Thanks -- I might get around to that at some point, but for now 
I'm ok waiting for pre-built binaries unless it becomes more of 
an issue (I've diverted far off what I need to be working on 
already).


The "Invalid memory operation" error is thrown only by the GC 
(AFAIK) when the user tries something unsupported like 
allocating or freeing in a destructor, while a GC collection is 
being run. I think that it's not possible to trigger it in 
@nogc code.
From a short debug session, I managed to find out that it 
crashes on the `++foos.length` line, somewhere inside this 
function: 
https://github.com/D-Programming-Language/druntime/blob/e47a00bff935c3f079bb567a6ec97663ba384487/src/rt/lifetime.d#L1265. Unfortunately I currently don't have enough time to investigate further.

Can you please file a bugzilla issue with this test case?


Done: https://issues.dlang.org/show_bug.cgi?id=15705

Thanks for the help!




Re: Arrays of noncopyables/Invalid memory operation

2016-02-19 Thread Matt Elkins via Digitalmars-d-learn

On Friday, 19 February 2016 at 01:30:13 UTC, H. S. Teoh wrote:
Suppose the array gets moved sometime after i=500 because it 
ran out of space in the current memory location.  Since there 
is another slice middleSlice pointing at the old data, it's not 
just a matter of *moving* the elements over to the new 
location; they have to be *copied* over so that there are now 
two copies of the original elements -- the GC doesn't know 
whether func may try to access the original elements through 
middleSlice, so it cannot just move them. Only when middleSlice 
goes out of scope, can the old elements be destructed.


So we see that when an array is grown, the elements cannot 
simply be moved to the new location; we must make copies of 
them, otherwise any slice of the old data will become invalid. 
So after an array is moved, there will be two copies of data, 
and if the original elements are unreferenced after all, the GC 
will call the dtors when it runs the next collection cycle.  
Then when the new elements become unreferenced, the dtors will 
be called again at the following collection cycle, on the new 
copies of the elements.


So it seems that the conclusion is that it is indeed unsafe to 
store non-copyable objects in an array which might grow (though 
it would be nice if attempting to do so was a compiler error, 
like it is with std.container.Array). I've starting creating a 
custom "Vector" type with value semantics which is move-aware, so 
hopefully that will address my needs.


Thanks for all the help, folks!


Arrays of noncopyables/Invalid memory operation

2016-02-17 Thread Matt Elkins via Digitalmars-d-learn
So in a different thread someone mentioned that when arrays are 
grown an implicit copy could be called on all the elements, as 
they might need to be copied over to a new, larger block of 
memory. This makes sense, and is expected. However, it got me 
concerned: what if the post-blit was disabled because it is 
illegal to copy the object? I am using a lot of objects exactly 
like this, and wanted to make sure my program wasn't working by 
coincidence since my dynamic arrays are still small for now. So I 
tested:


[code]
import std.stdio;
@safe:

bool scopeEnded;

struct Foo
{
@disable this(this);

this(int val) {writeln("Constructing: ", val, " (", , 
")"); value = val;}
~this() {writeln("Destroying: ", value, " (", , ")"); 
assert(value == int.init || scopeEnded);}

int value;
}

unittest
{
Foo[] foos;
for (auto i = 0; i < 1; ++i)
{
++foos.length;
foos[$ - 1] = Foo(i);
}

writeln("Scope about to end");
scopeEnded = true;
}
[/code]

[output]
Constructing: 0 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 1 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 2 (18FDA8)
Destroying: 0 (18FD6C)



Constructing: 410 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 411 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 412 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 413 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 414 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 415 (18FDA8)

Destroying: 0 (18FD6C)
core.exception.InvalidMemoryOperationError@src\core\exception.d(679): Invalid 
memory operation
Constructing: 416 (18FDA8)

Destroying: 0 (18FD6C)

Constructing: 417 (18FDA8)
core.exception.InvalidMemoryOperationError@src\core\exception.d(679): Invalid 
memory operation
Destroying: 0 (18FD6C)
Constructing: 418 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 419 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 420 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 421 (18FDA8)

Destroying: 0 (18FD6C)
Constructing: 422 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 423 (18FDA8)



Constructing: 506 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 507 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 508 (18FDA8)
Destroying: 0 (18FD6C)
Constructing: 509 (18FDA8)
Destroying: 0 (18FD6C)
Destroying: 29 (5201F4)
Program exited with code 1
[/output]

Note that the invalid memory operation lines change relative 
order in this output, I think maybe it is stderr instead of 
stdout.


So now I'm wondering:
* Is the fact that this compiles a bug? If copying can happen 
under the hood, shouldn't the @disable this(this) prevent Foo 
being used this way? Or should copying be happening at all (the 
compiler could instead choose to "move" the Foo by blitting it 
and NOT running the destructor...though I don't know whether that 
is a safe choice in the general case)?
* What is the invalid memory operation? It doesn't occur if I 
remove the assert or make the assert never fail, so I'm guessing 
it has to do with failing an assert in the destructor? This 
points bothers me less than the previous one because I don't 
expect an assert-failing program to behave nicely anyway.


Re: Confusion regarding struct lifecycle

2016-02-17 Thread Matt Elkins via Digitalmars-d-learn

On Wednesday, 17 February 2016 at 07:10:15 UTC, ZombineDev wrote:
The downside is that it really indicates that I didn't reduce 
my buggy program properly. I'll hold out for the 
live-object-destructor-call fix to see whether that corrects 
my problem; I can just leak resources until then :).


So I've reduced it more properly now, and am 98% sure I've just 
got another manifestation of that same bug.


BTW, you can try the nighly build which should include the bug 
fix:

http://dlang.org/download.html


I tried this, and got the same issue. Actually, I was still able 
to reproduce the original reported issue as well, which leads me 
to believe either the bug was not actually fixed or (and this is 
more likely) I screwed something up with my install. Do I need to 
do anything special to install a nightly build (I'm on Windows)? 
My "install" procedure was to move my dmd2 folder, verify that 
compilation now fails since there is no compiler installed, and 
then copy in the nightly build's dmd2 folder over the original 
path. Compilation then succeeds (but the bug still manifests).


That was running through my IDE (IntelliJ with the D language 
plugin), and then in turn through DUB. To remove variables, I 
also tried running dmd directly on the test file: dmd.exe test.d 
-unittest -main. This compiled but also reproduced the bug.


I guess the other possibility is that a patch was made and the 
issue marked resolved, but the patch hasn't been folded into the 
nightly build. I have no idea how dmd's patch/build/CI process 
works, so I don't know whether that is a real possibility.


Re: Confusion regarding struct lifecycle

2016-02-16 Thread Matt Elkins via Digitalmars-d-learn

On Wednesday, 17 February 2016 at 02:23:52 UTC, Ali Çehreli wrote:
Since a static array must consist of .init values to begin 
with, every move into its members must also trigger its 
destructor if the type has elaborate destructor.


Oof. This strikes me as a "gotcha", that this happens even with 
@disable this() as opposed to a compiler error. Is this only for 
static arrays, or are there other places @disable this() is 
silently ignored?



This is what I've discovered:


Ok, I think that pretty much explains the behavior I was seeing 
in the reduced case. Thanks -- that's helpful to know!


The downside is that it really indicates that I didn't reduce my 
buggy program properly. I'll hold out for the 
live-object-destructor-call fix to see whether that corrects my 
problem; I can just leak resources until then :).





Re: Confusion regarding struct lifecycle

2016-02-16 Thread Matt Elkins via Digitalmars-d-learn
After some more time spent on (the non-reduced version of) this, 
I think there is a decent chance I am really just experiencing 
another manifestation of a bug I reported a little bit ago: 
https://issues.dlang.org/show_bug.cgi?id=15661


The good news is that this is now marked as resolved, so 
hopefully the next build will have the patch and maybe my 
problems will go away :).





Re: Confusion regarding struct lifecycle

2016-02-16 Thread Matt Elkins via Digitalmars-d-learn

On Tuesday, 16 February 2016 at 10:45:09 UTC, Marc Schütz wrote:

On Tuesday, 16 February 2016 at 04:00:27 UTC, Mike Parker wrote:
On Tuesday, 16 February 2016 at 03:39:00 UTC, Matt Elkins 
wrote:
On Tuesday, 16 February 2016 at 03:31:51 UTC, maik klein 
wrote:

In D you can always call Foo.init even with @disable this(),


Foo.init can be called implicitly (not just explicitly)? If 
so, why even have @disable this(), if it offers no guarantees?


IMO, this is a bug. It should have to be explicit, just as it 
is with a single struct instance.


There is likely some bug here. In the example, though, the 
elements _are_ constructed explicitly (except foos[4]). This is 
legitimate, as the first assignment of an element in a 
construct counts as construction.


The elements are not constructed explicitly with Foo.init; they 
are constructed explicitly with a user-defined Foo constructor. 
Since default construction leads to a semantically-invalid object 
in the non-reduced case, I was expecting that a @disabled default 
constructor would cause the compiler to complain on attempts to 
default-construct the struct. Preferably this would be on any 
attempt to do so, including explicit calls to Foo.init, but at a 
minimum I would want it to complain on attempts to do so 
implicitly. Otherwise there don't appear to be any useful 
guarantees offered by @disable this().


Re: Confusion regarding struct lifecycle

2016-02-16 Thread Matt Elkins via Digitalmars-d-learn

On Tuesday, 16 February 2016 at 08:18:51 UTC, Ali Çehreli wrote:
When a temporary Foo object is moved into the array, the 
temporary object is set to Foo.init. This temporary object 
lives on the stack. In fact, all temporary Foo objects of 
Foo.this(int) live at the same location.


After Foo(8) is moved into the array and set to Foo.init, now 
Foo(1) is constructed on top of it. For that to happen, first 
the destructor is executed for the first life of the temporary, 
and so on...


There is one less Foo.init destruction because conceptually the 
initial temporary was not constructed on top of an existing 
Foo.init but raw memory.


I guess that makes sense. But doesn't it imply that a copy is 
happening, despite the @disabled post-blit? The desired behavior 
was to construct the Foos in place, like with a C++ initializer 
list.




Re: Confusion regarding struct lifecycle

2016-02-15 Thread Matt Elkins via Digitalmars-d-learn

On Tuesday, 16 February 2016 at 03:31:51 UTC, maik klein wrote:

In D you can always call Foo.init even with @disable this(),


Foo.init can be called implicitly (not just explicitly)? If so, 
why even have @disable this(), if it offers no guarantees?


The first 3 destructor calls are from the 3 Foo.inits in your 
static array.


But why only 3? There are 5 Foos in the array, and 4 were 
explicitly overwritten...




Confusion regarding struct lifecycle

2016-02-15 Thread Matt Elkins via Digitalmars-d-learn
I've been bitten again by my lack of understanding of the D 
struct lifecycle :-/. I managed to reduce my buggy program to the 
following example:


[code]
import std.stdio;

struct Foo
{
@disable this();
@disable this(this);

this(int valueIn) {value = valueIn;}
~this() {writeln("Foo being destroyed: ", value);}

int value;
}

struct FooList
{
@disable this();
@disable this(this);

this(int)
{
writeln("Before 8");
foos[0] = Foo(8);
writeln("Before 1");
foos[1] = Foo(1);
writeln("Before 2");
foos[2] = Foo(2);
writeln("Before 3");
foos[3] = Foo(3);
writeln("After Foo construction");
}

Foo[5] foos;
}

unittest
{
auto fooList = FooList(0);
writeln("About to lose scope");
}
[/code]

[output]
Before 8
Before 1
Foo being destroyed: 0
Before 2
Foo being destroyed: 0
Before 3
Foo being destroyed: 0
After Foo construction
About to lose scope
Foo being destroyed: 0
Foo being destroyed: 3
Foo being destroyed: 2
Foo being destroyed: 1
Foo being destroyed: 8
[/output]

There are a few things which confuse me about this:
* Why does this code compile? In particular, I would have 
expected that with Foo[5] but initialization for only Foos 0 .. 3 
and with the @disabled constructors in Foo, there would be a 
compiler error.
* Where do those first three destroyed Foos come from? I thought 
there should have been no Foos existing since default 
construction is @disabled...
* Even if somehow the Foos are being created despite the 
@disabled default constructor, why are only three Foos being 
destroyed before the scope is lost?


So I guess what I'm wondering is:
* If I @disable a default constructor on a struct, does the 
language guarantee that I won't have default-constructed 
instances of that struct? If not, what is the point of @disable 
for default constructors? If so, is the above situation a 
compiler bug or something I am missing?
* Is the below the right general syntax for creating an instance 
of a struct so as to avoid creating more than one copy? If not, 
what is?


Stack variable: auto foo = Foo(5);
Member variable: Foo m_foo; this(/* args */) {m_foo = Foo(5);}

Thanks!


Re: Things that keep D from evolving?

2016-02-12 Thread Matt Elkins via Digitalmars-d-learn
On Friday, 12 February 2016 at 14:03:05 UTC, Steven Schveighoffer 
wrote:

On 2/10/16 11:51 PM, Matt Elkins wrote:

* The in keyword. This is nice syntactic sugar over having a 
special
trait in C++ which deduces whether to pass by value or 
const-reference.

"foo(in bar)" is way more readable than something like
"foo(traits::fast_param bar)"


Hm... in is short for scope const. It is not pass by reference. 
Perhaps you meant auto ref?


Right...maybe I've been operating under false pretenses, but I 
was under the impression that the compiler was allowed to 
interpret scope const as either "pass by value" or "pass by const 
reference" freely so long as there was no custom post-blit 
defined? For the purposes of optimization, I mean, to avoid 
needless copying.


Re: Things that keep D from evolving?

2016-02-12 Thread Matt Elkins via Digitalmars-d-learn

On Friday, 12 February 2016 at 17:20:23 UTC, rsw0x wrote:
On Friday, 12 February 2016 at 15:12:19 UTC, Steven 
Schveighoffer wrote:

On 2/12/16 9:37 AM, Matt Elkins wrote:

[...]


Pass by reference and pass by value means different treatment 
inside the function itself, so it can't differ from call to 
call. It could potentially differ based on the type being 
passed, but I'm unaware of such an optimization, and it 
definitely isn't triggered specifically by 'in'. 'in' is 
literally replaced with 'scope const' when it is a storage 
class.


-Steve


note that 'in' and 'scope'(other than for delegates) parameter 
storage class usage should be avoided.

It really should be a warning.


Why is that?


Re: Things that keep D from evolving?

2016-02-12 Thread Matt Elkins via Digitalmars-d-learn
On Friday, 12 February 2016 at 15:12:19 UTC, Steven Schveighoffer 
wrote:

It could potentially differ based on the type being passed,


Yes, that's what I meant.


but I'm unaware of such an optimization,


Hm. Unfortunate.

and it definitely isn't triggered specifically by 'in'. 'in' is 
literally replaced with 'scope const' when it is a storage 
class.


Yeah, I didn't mean 'in' definitely triggered it. I meant that 
'in' (or rather, as you say, 'scope const') provides the 
conditions by which a compiler could make such an optimization, 
since it can know that the parameter will be unaffected by the 
function. It seems like that would mean it could, in theory, 
choose to pass small objects by value and large objects by 
reference under the hood, to avoid the large object copy 
(assuming no custom post-blit...and I guess it would have to 
check for taking the address?). To achieve that in C++ I use a 
special trait which deduces whether pass-by-value or 
pass-by-const-reference makes more sense for the type...but maybe 
I should be doing the same thing in D, if that optimization isn't 
actually present?


It does seem like the compiler could probably perform that 
optimization even if 'in' (or 'scope const') wasn't used, if it 
was smart enough...


This sort of micro-optimization generally doesn't matter at the 
application level unless one has actually profiled it. But it 
comes up a lot for me when writing generic libraries which can't 
know whether it will be used in a situation someday where those 
optimizations do actually matter.


Re: Things that keep D from evolving?

2016-02-10 Thread Matt Elkins via Digitalmars-d-learn

On Tuesday, 9 February 2016 at 13:41:30 UTC, NX wrote:
There are several reasons I want to use D rather than C# / Go / 
something else:


I will focus on comparing against C++, because that has been my 
favorite general purpose language for a long time. While I often 
have to use C, Java, C#, etc. for various business reasons, when 
faced with the choice on pure technical merits I will go for C++ 
any day (haven't tried Go, but was unimpressed by my initial 
read-over). D is the first language I have ever encountered with 
a serious chance of unseating C++ as my personal favorite.



- Interfacing with native API without jumping through hoops


Concur. Though I get this with C++, too.

- Incredibly high abstraction and meta-programming 
possibilities with relatively easier syntax + semantics.


Yes. The lack of powerful meta-programming is so frustrating in 
languages like Java and C#. C++ and D both have the power, but 
only D has the ease of reading and writing.


- It's harder to reverse engineer native code than byte code 
equivalent.


Meh. True, but this doesn't do much for me; it still isn't -that- 
hard to reverse native code, at least to the point of 
exploitation (to the point of copying is much harder). It just 
takes longer.



- Trading off anything according to your needs.


Yes. This is critical. I actually feel like D does this a little 
worse than C++ (though not significantly so), if only because it 
is difficult to completely avoid the GC, and if you want to avoid 
it and still use inheritance you need to break out the custom 
allocators. Most of the time this isn't a problem.



- Expressiveness and purity, immutablity concepts.


Expressiveness is key, though I haven't found D to be terribly 
more expressive than C++. A little better here, a little worse 
there. On the other hand, it is usually syntactically nicer when 
expressing concepts, sometimes greatly so.


Immutability is nice. The attention paid to threading was what 
caused me to take a closer look at D in the first place.



- Having GC (but not a horribly slow one)


Meh. I know there are things which are much easier to express 
with a GC, but they don't really come up for me. On the other 
hand, I often need deterministic cleanup, so the GC can be kind 
of an annoyance, since it lends itself to a lot of wrapping 
things in structs and forcing me to pay more attention to 
lifetime rules than I have to in C++.


The other (main?) purported benefits of a GC (avoiding leaks and 
dangling pointers) don't do much for me, since it is almost 
trivially easy to avoid those problems in C++ anyway, without 
introducing the headaches of the GC; certainly it is easier than 
the focus I have to give D object lifetimes now. That may be a 
matter of relative practice, though, since I've used C++ for a 
long long time and D for...3 weeks? :)


- Syntactic sugars (associtive arrays, powerful foreach, 
slices...)


I'm still adjusting to the idea of AAs as part of the language 
rather than library. Not sure I like it, but on the other hand it 
doesn't really hurt. The foreach construct isn't any better (or 
worse) than C++'s, unless I'm missing something (which is very 
possible). But slices are awesome!



- Compile times


Oh god yes. This makes metaprogramming so much more palatable.

- Not bound to a specific platform (unlike C#, easier to do 
cross-platform work in many cases)


I'll go it one step further, and note that D feels more portable 
than C++ to me...at least to the major platforms I usually work 
on. Maybe it's the simple fact that things like sockets are 
defined in the libraries, or that I don't have to #include 
 :).


I wish D could be better. I really want it with all of my 
heart...


D has a lot to offer. Here are a few other things I've really 
liked over C++:
* Modules. C++ is supposed(?) to get them at some point I 
suppose, but for here and now it's a clear advantage for D.
* Not syntactically separating interface and implementation 
(e.g., C++'s header vs source file dichotomy). This was never a 
true separation in C++, and just led to lots of extra syntax and 
minor DRY violations. Of course you could write everything inline 
anyway...until it depended on something declared later.
* Related to the point above, not having to think about whether 
to make something inline. Sure, C++ compilers make that choice 
for you, but you still have to decide whether to allow them (or 
at least the ones without link-time code generation) by putting 
your source in the header file. Needless headache for something a 
compiler can do.
* Properly doing away with the C preprocessor. I haven't seen a 
need for it that wasn't addressed by another D feature.
* Properly doing away with MI. Unlike some languages which just 
canned it, D actually replaced its functionality with other 
features.

* Thread-local by default. So simple. So useful.
* The in keyword. This is nice syntactic sugar over having a 
special trait in C++ which 

Re: Things that keep D from evolving?

2016-02-10 Thread Matt Elkins via Digitalmars-d-learn

On Thursday, 11 February 2016 at 05:05:22 UTC, tsbockman wrote:
On Thursday, 11 February 2016 at 04:51:39 UTC, Matt Elkins 
wrote:
- Syntactic sugars (associtive arrays, powerful foreach, 
slices...)


I'm still adjusting to the idea of AAs as part of the language 
rather than library. Not sure I like it, but on the other hand 
it doesn't really hurt. The foreach construct isn't any better 
(or worse) than C++'s, unless I'm missing something (which is 
very possible). But slices are awesome!


In D you can `foreach` over a list of types (AliasSeq) at 
compile time, not just over ranges at runtime. (For the moment, 
it's still only available in function bodies though, unlike 
`static if`.)


Neat! I didn't know that. You can do that in C++, but in typical 
fashion not with a convenient foreach statement. You have to do 
some crazy type list recursion stuff.


So chalk up another point for D's "ease of metaprogramming" :).


Re: Odd Associative Array Reference Behavior

2016-02-10 Thread Matt Elkins via Digitalmars-d-learn
On Thursday, 11 February 2016 at 03:47:09 UTC, Steven 
Schveighoffer wrote:

Misunderstanding.

An AA under the hood is simply a pointer. Initialized to null.

When you pass it around, you are passing a pointer. AA assign 
checks for null and allocates a new AA impl to hold the data. 
But this doesn't affect other copies (that were null).


So what is happening is aa() returns a null AA. You assign to 
it, which allocates a new AA impl, and sets the rvalue to point 
at it. The rvalue promptly disappears. The original m_aa is 
still set to point at null.


Makes sense (though it defies my intuition; I would have expected 
an NPE or crash at time of assignment). Thanks!




Odd Associative Array Reference Behavior

2016-02-10 Thread Matt Elkins via Digitalmars-d-learn
Consider the following definition of Foo and an accompanying 
unittest:


[code]
struct Foo
{
@property int[int] aa() {return m_aa;}
@property ref int[int] aaRef() {return m_aa;}
int[int] m_aa;
}

unittest
{
Foo foo;
assert(5 !in foo.m_aa); // Sanity-check to start off
foo.aa[5] = 1;  // Add an element with key 5
assert(5 !in foo.m_aa); // ...huh. 5 didn't make it in?
foo.aaRef[5] = 1;   // Try again, using the ref variant
assert(5 in foo.m_aa);  // Works!
}
[/code]

I was under the impression that associative arrays are reference 
types; if I pass a non-ref "copy" of one, shouldn't insertions 
still be reflected in the original? Am I dealing with a bug or a 
misunderstanding on my part?


Re: Odd Destructor Behavior

2016-02-08 Thread Matt Elkins via Digitalmars-d-learn

On Monday, 8 February 2016 at 07:31:07 UTC, Daniel Kozak wrote:

Seems to me too, please report it on issues.dlang.org


Reported: https://issues.dlang.org/show_bug.cgi?id=15661



Odd Destructor Behavior

2016-02-07 Thread Matt Elkins via Digitalmars-d-learn
I've been experiencing some odd behavior, where it would appear 
that a struct's destructor is being called before the object's 
lifetime expires. More likely I am misunderstanding something 
about the lifetime rules for structs. I haven't been able to 
reproduce with a particularly minimal example, so I will try to 
explain with my current code:


I have a struct called "TileView", with the relevant parts 
looking like so:

[code]
struct TileView
{
this(Texture.Handle wallsTexture, Texture.Handle topTexture)
{
// Work happens here, but it doesn't seem to matter to 
reproducing the condition

}

// Destructor added for debugging after seeing odd behavior
~this()
{
import std.stdio;
writeln("HERE2");
}
// ...more implementation that doesn't seem to affect the 
condition...

}
[/code]

An instance of this is stored in another struct called "View", 
with the relevant parts looking like so:

[code]
struct View
{
this(/* irrelevant args here */)
{
writeln("HERE1a");
m_tileView = 
TileView(Texture.create(loadTGA(makeInputStream!FileInputStream("resources/images/grass-topped-clay.tga").handle)), Texture.create(loadTGA(makeInputStream!FileInputStream("resources/images/grass-outlined.tga").handle)));//, Texture.create(loadTGA(makeInputStream!FileInputStream("resources/images/grass-outlined.tga").handle)));

writeln("HERE1b");
}

TileView m_tileView;
// ...more irrelevant implementation...
}
[/code]

The output from the two writelns in View and the one in TileView 
is:

[output]
HERE1a
HERE2
HERE1b
[/output]

So the destructor of TileView is being called during its 
construction. Flow proceeds normally (e.g., no exception is 
thrown), as demonstrated by "HERE1b" being printed. Interestingly 
enough, it all seems to hinge on the second argument to 
TileView's constructor; if I make it on a separate line 
beforehand and pass it in, or if I don't pass in a second 
argument at all, I don't see this behavior. In fact, almost any 
attempt I've made to reduce the problem for illustration causes 
it to vanish, which is unfortunate.


From this non-reduced situation, does anything jump out? Am I 
missing something about struct lifetimes? This is the only place 
I instantiate a TileView.


Thanks!




Re: Odd Destructor Behavior

2016-02-07 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 7 February 2016 at 22:35:57 UTC, anonymous wrote:

On 07.02.2016 23:07, Márcio Martins wrote:

The destructor you are seeing is from the assignment:

m_tileView = TileView(...);

This creates a temporary TileView, copies it to m_tileView, 
and then
destroys it. I suppose you want to move it instead. You need 
to copy the
handles from the temporary into the destination, and then 
clear them out

from the temporary to prevent them from being released.


I think you're mistaken here. The result of a struct literal is 
usually moved implicitly.


Code:

import std.stdio;

struct S
{
~this() {writeln("dtor");}
}

void main()
{
auto s = S();
writeln("end of main");
}


Output:

end of main
dtor


If there was a copy that's destroyed after the assignment, 
there should be another "dtor" before "end of main".


Yeah...and I just stuck this into TileView:
@disable this();
@disable this(this);

and it compiled just fine. If it created a copy I assume the 
compiler would have choked on that.


Re: Odd Destructor Behavior

2016-02-07 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 7 February 2016 at 22:04:27 UTC, anonymous wrote:

On 07.02.2016 22:49, Matt Elkins wrote:
 From this non-reduced situation, does anything jump out? Am I 
missing
something about struct lifetimes? This is the only place I 
instantiate a

TileView.


Looks weird. I presume this doesn't happen with simpler 
constructor parameters/arguments, like int instead of 
Texture.Handle? I don't see how the parameter types would make 
a destructor call appear. Might be a bug.


Correct; if I switch the second Texture.Handle to an int it 
doesn't happen. Nor if I remove it altogether. Nor if I create 
the Texture.Handle on the line immediately above TileView's 
construction, and then pass in the created Texture.Handle. I also 
didn't understand how the parameters would cause this.


Can you post the code for Texture, makeInputStream, etc, so 
that we have a full, reproducible test case?


Oi. Yes, I can, but it is quite a lot of code even if you don't 
count that it is dependent on OpenGL, GLFW, and gl3n to run to 
this point. This is why I was disappointed that simpler 
reproducing cases weren't appearing. I should probably spend more 
time trying to reduce the case some...


Re: Odd Destructor Behavior

2016-02-07 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 7 February 2016 at 23:11:34 UTC, anonymous wrote:

On 07.02.2016 23:49, Matt Elkins wrote:
Oi. Yes, I can, but it is quite a lot of code even if you 
don't count
that it is dependent on OpenGL, GLFW, and gl3n to run to this 
point.
This is why I was disappointed that simpler reproducing cases 
weren't
appearing. I should probably spend more time trying to reduce 
the case

some...


Minimal test cases are great, but if you're not able to get it 
down in size, or not willing to, then a larger test case is ok, 
too. The problem is clear, and I'd expect reducing it to be 
relatively straight-foward (but possibly time-consuming). Just 
don't forget about it completely, that would be bad.


Also be aware of DustMite, a tool for automatic reduction:

https://github.com/CyberShadow/DustMite


Turns out it was less hard to reduce than I thought. Maybe it 
could be taken down some more, too, but this is reasonably small:


[code]
import std.stdio;

struct TextureHandle
{
~this() {}
}

TextureHandle create() {return TextureHandle();}

 struct TileView
 {
 @disable this();
 @disable this(this);
 this(TextureHandle a, TextureHandle b) {}
 ~this() {writeln("HERE2");}
 }

 struct View
 {
 this(int)
 {
 writeln("HERE1a");
 m_tileView = TileView(create(), create());
 writeln("HERE1b");
 }

 private TileView m_tileView;
}

unittest
{
auto v = View(5);
}
[/code]

This yields the following:

[output]
HERE1a
HERE2
HERE1b
HERE2
[/output]

I would have expected only one "HERE2", the last one. Any of a 
number of changes cause it to behave in the expected way, 
including (but probably not limited to):
* Creating the TextureHandles directly rather than calling 
create()

* Using only one argument to TileView's constructor
* Removing TextureHandle's empty destructor

That last one especially seems to indicate a bug to me...


Re: Odd Destructor Behavior

2016-02-07 Thread Matt Elkins via Digitalmars-d-learn

Some environment information:
DMD 2.070 32-bit
Windows 7 (64-bit)


Re: Ownership semantics

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 20:10:03 UTC, Matt Elkins wrote:
On Sunday, 31 January 2016 at 20:07:26 UTC, Steven 
Schveighoffer wrote:
What is likely happening is that ptr is already collected, and 
you are invalidly attempting to re-free it.


The GC can collect this memory even though there is still an 
outstanding root-reachable pointer to it?


Or maybe it isn't root-reachable?


Re: Ownership semantics

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn
On Sunday, 31 January 2016 at 20:07:26 UTC, Steven Schveighoffer 
wrote:
What is likely happening is that ptr is already collected, and 
you are invalidly attempting to re-free it.


The GC can collect this memory even though there is still an 
outstanding root-reachable pointer to it?


Re: Ownership semantics

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn
On Sunday, 31 January 2016 at 20:20:52 UTC, Steven Schveighoffer 
wrote:

Oh, nevermind. This is actually simpler.

You can't do memory operations inside a destructor during 
collection. I forgot about that.


But the rule I stated is still in force.

-Steve


So this implies that the UniquePtr implementation originally 
posted might work with malloc/free calls, or some other non-GC 
allocator...of course, in that case one could just use 
std.typecons.Unique.


Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn
I know I can mark an argument ref to require lvalues, so I'm 
wondering whether there is an equivalent for rvalues; that is, is 
there a way to specify that an argument to a function MUST be an 
rvalue?


For example, in C++ I can do this:
[code]
void foo(int && x) {...}

foo(5); // Works fine
int y = 5;
foo(y); // Compile error; y is not an rvalue
[/code]

This functionality turns out to be really useful when dealing 
with transferring ownership of resources.


Re: Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn
Errr, ignore the makeFoo() line. Left that in by accident, has no 
bearing on the issue.


Re: Ownership semantics

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 19:34:43 UTC, maik klein wrote:
I recently asked a question about ownership semantics in D 
https://stackoverflow.com/questions/35115702/how-do-i-express-ownership-semantics-in-d


But a few minutes ago I found an answer on SO that could 
potentially explain a lot.


http://stackoverflow.com/a/35114945/944430

Sadly it has some pseudo code in it so I implemented it with 
std.experimental.allocator


struct UniquePtr(T) {
import std.experimental.allocator;
private T* ptr = null;

@disable this(this); // This disables both copy 
construction and opAssign


this(Args...)(auto ref Args args){
ptr = theAllocator.make!T(args);
}

~this() {
theAllocator.dispose(ptr);
}

inout(T)* get() inout {
return ptr;
}

// Move operations
this(UniquePtr!T that) {
this.ptr = that.ptr;
that.ptr = null;
}

ref UniquePtr!T opAssign(UniquePtr!T that) { // Notice no 
"ref" on "that"

import std.algorithm.mutation;
swap(this.ptr, that.ptr); // We change it anyways, 
because it's a temporary

return this;
}
}

Is this code correct? One problem that I have is

UniquePtr!int[int] map;

will result in a memory exception and I have no idea why.


Interesting. It is something in the dispose, because I changed 
the destructor to:


[code]
~this()
{
writeln("Disposing ", ptr, " for this ", );
theAllocator.dispose(ptr);
writeln("Disposed ", ptr, " for this ", );
}
[/code]

And I only get the disposing line, not the disposed.

I tried taking my ResourceHandle struct that I pasted to you in 
the other thread earlier and doing the same operation with it (I 
had to change a const to inout and remove an extraneous 'in' 
marker to make it compile):


[code]
alias RH = ResourceHandle!(int*, (int* ptr) 
{theAllocator.dispose(ptr);});

RH[int] otherMap;
otherMap[3] = RH(theAllocator.make!int(5));
[/code]

and I get the same invalid memory operation. With either class, I 
avoid the error if I use a stack member or a static array, but 
with the associative array or just a dynamic array I get the 
problem.


To see it in a dynamic array:
[code]
auto map = new UniquePtr!int[1];
map[0] = UniquePtr!int(5);
[/code]

Not sure what it is...still playing with it.


Re: Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 18:02:19 UTC, Matt Elkins wrote:

Here is the one I am using right now:


Actually, here is the whole module in case you are interested in 
the unittests/usage:


[code]
import std.algorithm;
import std.traits;

struct ResourceHandle(T, alias Deleter, T Default = T.init)
{
// Constructors/Destructor
this(in T handle) {m_handle = handle;}
@disable this(this);
~this() {Deleter(m_handle);}

// Operators
@disable void opAssign(ref ResourceHandle lvalue);
ref ResourceHandle opAssign(ResourceHandle rvalue) 
{swap(m_handle, rvalue.m_handle); return this;}


// Methods
@property T handle() const {return m_handle;}
@property T handle(T handle) {Deleter(m_handle); m_handle = 
handle; return m_handle;}
T release() {T result = m_handle; m_handle = Default; return 
result;}


private:
T m_handle = Default;
}

@nogc @safe nothrow unittest
{
static uint destroyedCount;
static uint lastDestroyed;
alias RH = ResourceHandle!(uint, (uint resource){if (resource 
!= uint.init) {lastDestroyed = resource; ++destroyedCount;}});


// Test basic resource cleanup
assert(destroyedCount == 0);
assert(lastDestroyed != 7);
{auto handle0 = RH(7);}
assert(destroyedCount == 1);
assert(lastDestroyed == 7);

// Test releasing
{
auto handle0 = RH(8);
assert(handle0.handle == 8);
assert(handle0.release() == 8);
assert(handle0.handle == uint.init);
assert(destroyedCount == 1);
assert(lastDestroyed == 7);
}
assert(destroyedCount == 1);
assert(lastDestroyed == 7);

{
// Test that copying and lvalue assignment are disabled
auto handle0 = RH(5);
static assert (!__traits(compiles, {auto handle1 = 
handle0;}));
static assert (!__traits(compiles, {RH handle1; handle1 = 
handle0;}));


// Test that rvalue assignment works
auto makeRH(uint value) {return RH(value);}
handle0 = makeRH(3);
assert(destroyedCount == 2);
assert(lastDestroyed == 5);
}
assert(destroyedCount == 3);
assert(lastDestroyed == 3);

// Test setting in static array
{
RH[3] handles;
handles[0] = RH(9);
assert(destroyedCount == 3);
assert(lastDestroyed == 3);
}
assert(destroyedCount == 4);
assert(lastDestroyed == 9);

// Test setting to resource directly
{
auto handle0 = RH(11);
assert(destroyedCount == 4);
assert(lastDestroyed == 9);
assert(handle0.handle == 11);
handle0.handle = 12;
assert(destroyedCount == 5);
assert(lastDestroyed == 11);
assert(handle0.handle == 12);
}
assert(destroyedCount == 6);
assert(lastDestroyed == 12);
}
[/code]


Re: Ownership semantics

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 20:11:07 UTC, Matt Elkins wrote:

On Sunday, 31 January 2016 at 20:10:03 UTC, Matt Elkins wrote:
On Sunday, 31 January 2016 at 20:07:26 UTC, Steven 
Schveighoffer wrote:
What is likely happening is that ptr is already collected, 
and you are invalidly attempting to re-free it.


The GC can collect this memory even though there is still an 
outstanding root-reachable pointer to it?


Or maybe it isn't root-reachable?


No, it is still present even if root-reachable:

[code]
unittest
{
import std.algorithm;

int* x;
{
auto map = new UniquePtr!int[1];
auto uniqueX = UniquePtr!int(5);
x = uniqueX.get();
map[0] = move(uniqueX);
}
}
[/code]

[output]
core.exception.InvalidMemoryOperationError@src\core\exception.d(679): Invalid 
memory operation

Program exited with code 1
Made 632560 for this 18FD90
Disposing null for this 18FD70
Disposed null for this 18FD70
Disposing null for this 18FD90
Disposed null for this 18FD90
All unit tests have been run successfully.
Disposing 632560 for this 632550
[/output]


Re: Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:42:19 UTC, anonymous wrote:
I don't know if this works in all cases, but it passes that 
simple test:



@disable void foo(ref int x);
void foo(int x) {}

void main()
{
foo(5); /* works */
int y = 5;
foo(y); /* error */
}



My fault, I should have better explained the situation I'm 
running into. I've boiled it down to this:


[code]
struct Foo
{
@disable this(this);
@disable void opAssign(ref Foo);
void opAssign(Foo foo) {}
}

unittest
{
void bar(Foo foo)
{
Foo foo1;
foo1 = foo; // Fails to compile here
}
Foo makeFoo() {return Foo();}
bar(Foo());
}
[/code]

[output]
Error: function Foo.opAssign is not callable because it is 
annotated with @disable

[/output]

Note that if I don't declare and assign foo1 on separate steps it 
yells at me for the post-blit constructor being disabled, which 
is reasonable. But it seems like the rvalue assignment operator 
should work...


Re: Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:48:53 UTC, maik klein wrote:
The problem is that x will be copied afaik which is not what 
you want if you want to deal with ownership.


I think that can be solved by wrapping the resource in a struct 
that deals with passing the ownership. Here is the one I am using 
right now:


[code]
struct ResourceHandle(T, alias Deleter, T Default = T.init)
{
// Constructors/Destructor
this(in T handle) {m_handle = handle;}
@disable this(this);
~this() {Deleter(m_handle);}

// Operators
@disable void opAssign(ref ResourceHandle lvalue);
ref ResourceHandle opAssign(ResourceHandle rvalue) 
{swap(m_handle, rvalue.m_handle); return this;}


// Methods
@property T handle() const {return m_handle;}
@property T handle(T handle) {Deleter(m_handle); m_handle = 
handle; return m_handle;}
T release() {T result = m_handle; m_handle = Default; return 
result;}


private:
T m_handle = Default;
}
[/code]


Re: Declaring rvalue function arguments

2016-01-31 Thread Matt Elkins via Digitalmars-d-learn

On Sunday, 31 January 2016 at 17:55:53 UTC, Matt Elkins wrote:
Errr, ignore the makeFoo() line. Left that in by accident, has 
no bearing on the issue.


Ok, I think I understand why this doesn't work, at least. The Foo 
passed into bar() is, of course, an lvalue itself.


So I can achieve this with a new bar(), like so:

[code]
void bar(Foo foo)
{
import std.algorithm.mutation;
Foo foo1 = move(foo);
}
[/code]


Re: Access Violation in @safe Code

2016-01-30 Thread Matt Elkins via Digitalmars-d-learn

On Saturday, 30 January 2016 at 13:37:43 UTC, Kagamin wrote:
Alias templates require stack pointer, init probably has it set 
to null.

Try this:
FooType foo = FooType();


Yes, that fixed it. Interesting.


Re: Relocatable objects and internal pointers

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn

On Saturday, 30 January 2016 at 01:28:54 UTC, H. S. Teoh wrote:
On Sat, Jan 30, 2016 at 01:21:27AM +, Matt Elkins via 
Digitalmars-d-learn wrote:
On Saturday, 30 January 2016 at 01:18:33 UTC, Ali Çehreli 
wrote:
>Definitely so. Rvalues are moved around all the time. The 
>following program has two rvalue moves without calling 
>post-blits or destructors.


Oi, that makes life tough. Ok, I'll figure something else out, 
then...

[...]

Keep in mind that D structs are conceptually different from C++ 
structs (even if they are similarly implemented). D structs are 
supposed to be value types with POD-like semantics; so when 
passing structs around they are bit-copied into the destination 
and then the postblit method (this(this)) is called to "patch 
up" the copy. This is unlike in C++ where you have copy ctors 
and dtors and operator=() to manage copying.


Because there are no copy ctors, having internal pointers can 
be dangerous, since structs can move around in memory without 
any warning (e.g., returning a struct from a function generally 
involves copying it from the callee's stack frame into a local 
variable in the caller's stack frame).


If you need something with internal pointers, you might want to 
consider classes instead. Either that, or be sure to allocate 
your structs on the heap instead, and work with pointers 
instead of the struct values directly. (Note that this is still 
risky, since somebody might dereference the pointer and get a 
stack copy of the struct, which will cause problems when it 
then gets passed around.)



T


Yeah, but the whole point of what I am doing is to avoid using 
the heap; I can think of several ways to implement this if I 
relax that restriction :). I'm basically trying to make C++'s 
std::unique_ptr for resource handles, a thin wrapper which 
ensures resource cleanup and allows moving the handle. Since I'm 
putting it in my lowest-level/most-generic library with no 
visibility on how it gets used, I want it very lightweight 
(ideally zero-cost, like I can do in C++11, or at least low-cost 
[sans heap] like I could do in C++98) so that I can use it with 
the broadest range of higher-level applications.


Relocatable objects and internal pointers

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn
Hi all, I'm a C++ programmer trying to decide whether to switch 
my main focus to D, and so I'm working on a pet project using it. 
So far I really like some of the practical aspects of the 
language (built-in contracts are great, the metaprogramming is 
very accessible, and I can't enough of these compile speeds!), 
but I keep finding myself frustrated by what seem like 
expressiveness limitations (unless, as I hope, they are just 
examples of my newbieness shining through). Case in point:


In an attempt to work around one apparent limitation (previously 
asked about here 
http://forum.dlang.org/thread/eizmagtimvetogana...@forum.dlang.org) I came up with an idea which would require storing internal points in a struct. A very stripped-down but illustrative example would be something like this:


[code]
struct Foo
{
invariant
{
assert(m_this == );
}

@disable(this);

this(/* arguments to populate stuff */)
{
m_this = 
/* ... populate stuff ... */
}

this(this)
{
m_this = 
/* ... do more stuff ... */
}

private:
Foo* m_this;
/* ... stuff ... */
}
[/code]

This is just a piece of what I am doing, if you are wondering why 
I am bothering to save a pointer to this. However, I was doing 
some reading on D and came across a section in TDPL which said 
internal pointers are verboten because objects must be 
relocatable. Does this mean my example is invalid (e.g., the 
invariant will not hold in all circumstances)? If it is invalid, 
does that mean there are circumstances under which the post-blit 
constructor can be elided when performing a copy or copy-like 
operation (such as a move)? I've been treating it like a sort of 
copy-constructor that lacks visibility on the copied-from object, 
but maybe that's a mistake...


Re: Access Violation in @safe Code

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn
On Saturday, 30 January 2016 at 05:18:08 UTC, Steven 
Schveighoffer wrote:

https://issues.dlang.org/enter_bug.cgi

-Steve


Added!
https://issues.dlang.org/show_bug.cgi?id=15627

Thanks for the help.



Re: Relocatable objects and internal pointers

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn
On Saturday, 30 January 2016 at 02:09:55 UTC, Steven 
Schveighoffer wrote:
I figured out a way to have them. You just have to guarantee 
you don't copy the actual "pointer" out of the struct:


https://forum.dlang.org/post/mk5k4l$s5r$1...@digitalmars.com


Unfortunately, that won't work for what I was trying to do. The 
stuff I elided in the comments were more pointers to other Foo 
instances, used to create a linked-list (of stack-allocated 
objects); these would still break under the conditions Ali 
described. I was only storing the this pointer so that blitted 
objects could deduce where they came from (trying to turn the 
post-blit constructor into a copy-constructor).


Thanks, though. I'm thinking that maybe D just can't express 
these semantics without substantial overhead. While somewhat 
disappointing (I came into D with stars in my eyes :)), it's not 
enough by itself to make me go back to C++, at least not just 
yet. Not when I can just use a few static ifs to do what 
previously required careful template crafting that I wouldn't 
understand 3 months later. On the other hand, I'm falling behind 
on my library books since I no longer have any time for reading 
during compilations ;).


Re: Relocatable objects and internal pointers

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn
On Saturday, 30 January 2016 at 03:00:11 UTC, Steven 
Schveighoffer wrote:
There are some really smart people who frequent these forums, 
if you post your actual use case, you may get an answer that 
you hadn't thought of.


Yeah, I tried that first (on the general forum, since at the time 
I didn't know about this one).


I saw you were trying to implement something like 
std::unique_ptr? There is 
http://dlang.org/phobos/std_typecons.html#.Unique


std.typecons.Unique seems to require heap allocation, which makes 
it a far cry from std::unique_ptr.


Conditional nothrow/safe/nogc/etc?

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn
Is there any way to specify that a generic function is 
conditionally nothrow (or other function decorators), based on 
whether the template instantiation is nothrow? I'm looking for 
something akin to C++'s noexcept(noexcept()), e.g.:


template  void foo() noexcept(noexcept(T())) {}

I don't see anything about it on the functions grammar page 
(https://dlang.org/spec/function.html). I do see something to do 
with nothrow_ on the std.traits page, but I'm not sure how to use 
it to achieve this or whether that is the right approach.


My actual use case is a non-generic method opAssign inside of a 
generic struct.


Access Violation in @safe Code

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn
Title says it; I get an access violation in code marked @safe. 
Here's a minimal example:


[code]
@safe:

struct Foo(alias Callback)
{
~this() {Callback();}
}

unittest
{
uint stackVar;
alias FooType = Foo!((){++stackVar;});

FooType[1] foos;
foos[0] = FooType.init;
}
[/code]

This results in:
object.Error@(0): Access Violation

0x00405E2A in pure nothrow @nogc @safe void 
test.__unittestL9_4().__lambda1() at \test.d(12)

... more stack ...

Line 12 is the alias FooType line, where the delegate is defined.

Where is this coming from? Intuition says it is something to do 
with calling the delegate after the stack frame has popped and 
stackVar is unreachable, but I'm not seeing it. Wouldn't foos be 
destructed before the stack frame is gone?


I don't get the issue if I mark stackVar static, or if I don't 
perform the assignment to foos[0].


Re: Conditional nothrow/safe/nogc/etc?

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn
On Saturday, 30 January 2016 at 05:25:49 UTC, Rikki Cattermole 
wrote:

On 30/01/16 6:17 PM, Matt Elkins wrote:

[...]


templated functions have attribute inference. Meaning if it can 
be nothrow it will be.
Regarding your real use case, again struct if templated so it 
should be inferred.


Convenient! Thanks!


Re: Conditional nothrow/safe/nogc/etc?

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn

On Saturday, 30 January 2016 at 05:57:34 UTC, H. S. Teoh wrote:
A common idiom that we use is to write an attributed unittest 
to verify that the function itself is @safe/etc.. This way, if 
instantiated with safe/etc. types, the template will also be 
safe/etc., but if instantiated with an unsafe type, it will 
correspondingly be unsafe (instead of failing to compile if you 
wrote @safe on the template). The unittest ensures that you do 
not accidentally introduce un-@safe code into the template and 
cause *all* instantiations to become un-@safe.


auto mySafeCode(T)(T t) { ... }

@safe unittest
{
auto x = mySafeCode(safeValue);
}


T


Seems sound. Thanks!



Re: Relocatable objects and internal pointers

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn

On Saturday, 30 January 2016 at 01:18:33 UTC, Ali Çehreli wrote:
Definitely so. Rvalues are moved around all the time. The 
following program has two rvalue moves without calling 
post-blits or destructors.


Oi, that makes life tough. Ok, I'll figure something else out, 
then...


Thanks for the response!


Re: d plugin for Intelij Idea debuging support

2016-01-29 Thread Matt Elkins via Digitalmars-d-learn

On Friday, 29 January 2016 at 12:00:25 UTC, Pavel wrote:

Hello!

Is there any debuging support for Intelij Idea's D plugin?

Thanks!


I can't say for certain, but the website 
(https://github.com/kingsleyh/DLanguage) lists this as an 
upcoming feature by the end of 2016, so I think there probably 
isn't any support yet?


I use this plugin, too, it's pretty awesome.