Re: Storing interfaces as void[]

2021-03-12 Thread David Zhang via Digitalmars-d-learn

On Friday, 12 March 2021 at 22:18:59 UTC, tsbockman wrote:
Why do you think you need a `void[]` slice? I think `void*` 
pointers are sufficient. This handles all normal data types, as 
long as they are allocated on the GC heap:


I wanted to have the registry own the structs' memory, though 
using new makes more sense on second thought. Your example 
templated implementation makes so much sense, though it doesn't 
work in this case. Thanks for the idea though.



Aye, I'm using hashes. The idea is to support either D 
interfaces or structs with arbitrary content.


You can use TypeInfo references as the keys for the struct 
types, too. It's better than hashes because the TypeInfo is 
already being generated anyway, and is guaranteed to be unique, 
unlike your hashes which could theoretically collide.


Makes sense. Using TypeInfo never occurred to me. I assume they 
are generated for COM classes as well?


`I` is *not* the type of an interface instance, it is the 
type of a reference to an instance of the interface.


So `I i` is a reference to the instance, which itself holds a 
reference to the implementation, like a reference to a 
delegate (pointer to (ctx, fn))?


No. What you are calling "the implementation" is the same thing 
as "the instance". `I i` is a reference into the interior of 
the implementing class instance, offset such that it points at 
the virtual function table pointer for that interface. The 
lowering is something like this:



interface I { ... }
class C : I { ... }
struct C_Instance {
void* __vtblForC;
// ... other junk
void* __vtblForI;
// ... explicit and inherited class fields, if any.
}

C c = new C; // Works like `C_Instance* c = new C_Instance;`
I i = c; // Works like `void** i = 
(C_Instance.__vtblForI.offsetof + cast(void*) c);`


Makes sense, I always thought of them as existing in separate 
places.


So much head-bashing, and it's over. Thanks, tsbockman, 
Imperatorn.




Re: Storing interfaces as void[]

2021-03-12 Thread David Zhang via Digitalmars-d-learn

On Friday, 12 March 2021 at 18:14:12 UTC, Imperatorn wrote:

On Friday, 12 March 2021 at 17:57:06 UTC, David  Zhang wrote:

On Friday, 12 March 2021 at 17:46:22 UTC, Imperatorn wrote:

On Friday, 12 March 2021 at 17:37:43 UTC, David  Zhang wrote:

[...]


Have you tried using Variant or jsvar 
(https://code.dlang.org/packages/arsd-official%3Ajsvar)? 樂


It doesn't appear to support interfaces, see opAssign at line 
682.


It occurs to me that I.sizeof == 8 which is just enough for 
the vtbl, but not enough for an implementation ptr. Maybe it's 
a pointer to a {self, vtbl} pair? SomeClass.sizeof == 16, 
which is enough storage for both...


Did you try Variant? Seems to work for me


It seems a bit overkill for this. I also want to be able to track 
memory usage here, and Variant doesn't appear able to store 
arbitrary-sized structs without untrackable allocations. The idea 
has merit, but doesn't give me the control I desire :)


Re: Storing interfaces as void[]

2021-03-12 Thread David Zhang via Digitalmars-d-learn

On Friday, 12 March 2021 at 18:50:26 UTC, tsbockman wrote:




The idea is to implement a service locator s.t. code like this is 
possible:


// struct (I didn't mention this in the top post, my mistake)
auto log = Logger()
api_registry.register!Logger(log);

// class/interface
auto input = new InputReplay(recorded_input);
api_registry.register!InputStream(input);

//
// somewhere else
//

// interface
auto input = api_registry.get!InputStream();
// do something with input.

// struct*
api_registry.get!Logger().info(...);

//
// and additionally
//

auto input = new KeyboardInput(...);
api_registry.replace!InputStream(input);

/* Fully qualified names can be *very* long because of 
templates, so it can be wasteful to store and compare them at 
runtime. Let's use `TypeInfo` instead: */


Aye, I'm using hashes. The idea is to support either D interfaces 
or structs with arbitrary content.


`I` is *not* the type of an interface instance, it is the type 
of a reference to an instance of the interface.


So `I i` is a reference to the instance, which itself holds a 
reference to the implementation, like a reference to a delegate 
(pointer to (ctx, fn))? Thus cast(void*) produces something like 
*(ctx, fn). I don't mind that. I just want to store that 
reference as void[], be able to replace with with some other 
reference to another implementation as void[], then retrieve that 
as a reference intact.


I don't really need to copy or move the class instances here, 
just be able to read, assign, and replace references to them in 
the same place that I read, assign, and replace void[]'s of 
structs.


Re: Storing interfaces as void[]

2021-03-12 Thread David Zhang via Digitalmars-d-learn

On Friday, 12 March 2021 at 17:46:22 UTC, Imperatorn wrote:

On Friday, 12 March 2021 at 17:37:43 UTC, David  Zhang wrote:
I want to store interfaces as untyped void[], then cast them 
back to the interface at a later time. However, it appears to 
produce garbage values on get().


Is this even possible, and if so, what is happening here? The 
alternative would be a struct { CheckedPtr self; api_fns }


e.g.

void register(I)(I i) {
  auto mem = new void[](I.sizeof);
  memcpy(mem.ptr, cast(void*) i, I.sizeof);

  // CheckedPtr includes a hash of fullyQualifiedName
  map[i.get_name()] = CheckedPtr!I(mem.ptr);
}

I get(I)() {
  // basically cast(I) p
  return map[I.get_name()].as!I();
}


Have you tried using Variant or jsvar 
(https://code.dlang.org/packages/arsd-official%3Ajsvar)? 樂


It doesn't appear to support interfaces, see opAssign at line 682.

It occurs to me that I.sizeof == 8 which is just enough for the 
vtbl, but not enough for an implementation ptr. Maybe it's a 
pointer to a {self, vtbl} pair? SomeClass.sizeof == 16, which is 
enough storage for both...


Storing interfaces as void[]

2021-03-12 Thread David Zhang via Digitalmars-d-learn
I want to store interfaces as untyped void[], then cast them back 
to the interface at a later time. However, it appears to produce 
garbage values on get().


Is this even possible, and if so, what is happening here? The 
alternative would be a struct { CheckedPtr self; api_fns }


e.g.

void register(I)(I i) {
  auto mem = new void[](I.sizeof);
  memcpy(mem.ptr, cast(void*) i, I.sizeof);

  // CheckedPtr includes a hash of fullyQualifiedName
  map[i.get_name()] = CheckedPtr!I(mem.ptr);
}

I get(I)() {
  // basically cast(I) p
  return map[I.get_name()].as!I();
}


Re: How to create an overwriteable struct that is always const?

2019-06-02 Thread David Zhang via Digitalmars-d-learn

Ah, fair enough.


Re: How to create an overwriteable struct that is always const?

2019-06-01 Thread David Zhang via Digitalmars-d-learn

On Saturday, 1 June 2019 at 13:00:50 UTC, ag0aep6g wrote:


How is setting/replacing different from modifying?


e.g.:

S s;

this() { s = ...; }

update(S s) { this.s = s; }

mod(int i) { s.i = i; } // illegal

Kinda like how strings can be copied and assigned to, but not 
modified.




Re: How to create an overwriteable struct that is always const?

2019-06-01 Thread David Zhang via Digitalmars-d-learn

On Saturday, 1 June 2019 at 16:30:12 UTC, Jonathan M Davis wrote:
If any member variable of a struct is const, then you can't 
modify that member ever, and assignment isn't possible unless 
you override opAssign so that it overwrites only the mutable 
members. It's very rare that it makes sense to make any member 
variables of a struct const or immutable, because then you 
basically can't use assignment anymore.


You could make all of the member variables private and provide 
no functions that set any of them, then the only way to change 
any of their values would be to construct a new value of that 
type and assign it to the variable.


- Jonathan M Davis


Ideally, I'd like for member functions to be checked against 
modifying s also, not just externally.


How to create an overwriteable struct that is always const?

2019-06-01 Thread David Zhang via Digitalmars-d-learn

Say I have a struct `S`:

struct S {
/*const*/ char* pointer;
... other members ...

this(/*const*/ char* p, ... others ...) {
pointer = p;
...
}
}

What I want, is to be able to use `S` in other data structures 
with the following properties checked by the compiler:


 - The variable can be set
 - The variable can be read
 - The variable cannot be modified, only replaced

Is there a type-safe way to do this? If this were a class, I'd 
try std.typecons.Rebindable.


Thanks


Re: Getting a reference to an immutable string

2018-02-10 Thread David Zhang via Digitalmars-d-learn

On Saturday, 10 February 2018 at 22:59:18 UTC, ag0aep6g wrote:
But there is a recent regression on Windows that might be 
related. Do you also have a static constructor (`static this`) 
that uses `wndclassName`? If so, you might be hitting issue 
18412.


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

If you don't have a static constructor, it might be a different 
bug. In that case, please provide complete code so that we can 
get to the bottom of it.


I have a static constructor that uses wndclassName to register 
the window class... at the top of the file.


I think that's the bug.


Re: Getting a reference to an immutable string

2018-02-10 Thread David Zhang via Digitalmars-d-learn
Building with Visual Studio seems to be fine. This isn't an 
OptLink issue, is it?


Re: Getting a reference to an immutable string

2018-02-10 Thread David Zhang via Digitalmars-d-learn

On Saturday, 10 February 2018 at 22:36:41 UTC, ag0aep6g wrote:

On 02/10/2018 11:26 PM, David Zhang wrote:
I've got an immutable string declared in module scope, and I 
attempted to get a pointer to its characters through both 
[0] and str.ptr. However, it appears to me that the string 
is behaving like a manifest constant, in that the pointer is 
null.


The language reference indicates that it has a location in 
memory and thus has a pointer.


So, my question is thus: Is this a bug in DMD, or is this just 
something I missed?


The pointer should not be null, even when `str` is a manifest 
constant. But without code it's impossible to say if you're 
hitting a compiler bug or if you're doing something wrong.


Ah, yeah.

It appears to occur only when compiled in x86 mode.

This is what I'm talking about:

void createWindow( ... ) {

assert( wndclassName.ptr ); //This fails

HWND hwnd = CreateWindowW(
wndclassName.ptr, //This too
null,
0,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
null,
null,
null,
null
);
}

wstring wndclassName = "wndclass_name"w;


Getting a reference to an immutable string

2018-02-10 Thread David Zhang via Digitalmars-d-learn

Hi,

I've got an immutable string declared in module scope, and I 
attempted to get a pointer to its characters through both [0] 
and str.ptr. However, it appears to me that the string is 
behaving like a manifest constant, in that the pointer is null.


The language reference indicates that it has a location in memory 
and thus has a pointer.


So, my question is thus: Is this a bug in DMD, or is this just 
something I missed?


Thanks

David


Re: String copying fails when output from assert

2017-11-21 Thread David Zhang via Digitalmars-d-learn
On Tuesday, 21 November 2017 at 19:05:21 UTC, Jonathan M Davis 
wrote:
Well, the assertion is going to throw an AssertError, which 
takes a string for its message. It doesn't copy the contents of 
the string. It's just taking a slice just like whenever you 
pass a string to any other function. So, it refers to the same 
memory as what's passed in. So, if what it's passed is a string 
that refers to memory on the stack, then when it goes to print 
the message, it's going to be garbage, because the stack was 
unwound, and the static array is gone.


Honestly, I'd argue that it's a bug that it allows you provide 
a message as a char[] instead of immutable(char)[]. It seems 
that the compiler is implicitly converting char[] to 
immutable(char)[] in this case, which is very bad. It would 
matter less if you were giving the assertion a char[] that 
referred to memory on the heap, but it still shouldn't be 
allowed.


You really should be giving assertions a value that is an 
actual string that lives on the heap when providing a message, 
not a char[], and definitely not a char[] that's a slice of a 
static array.


- Jonathan M Davis


Right. So a literal would work, because it's in the .data 
segment, or inlined. Basically, only strings from the heap, or 
that are compiled into the code are valid for assert messages.


What kind of behavior would an assert from stdc have (id, 
betterC)?


Re: String copying fails when output from assert

2017-11-21 Thread David Zhang via Digitalmars-d-learn

On Tuesday, 21 November 2017 at 18:56:03 UTC, Adam D. Ruppe wrote:
On Tuesday, 21 November 2017 at 18:49:40 UTC, David  Zhang 
wrote:

assert(false, chars[0..str.length]);
}

What am I missing here?


You're escaping a reference to a local variable there. chars[] 
is a pointer to the stack, which is promptly smashed when the 
assert error starts working up the call chain, so by the time 
it actually prints, you have undefined behavior.


So I'd have to allocate the buffer on the heap then...
Is there any way to do this without allocating to the stack?


String copying fails when output from assert

2017-11-21 Thread David Zhang via Digitalmars-d-learn

Hi,

I've been trying to copy a string, then output it from an 
`assert(false)` statement, but the copy seems to be corrupted 
somehow.


void main()
{
string str = "some string";

//initializing `chars` with any value doesn't do anything
char[64] chars;
//char[64] chars = '!';

//memcpy doesn't work either, though the output's different
//import core.stdc.string;
//memcpy([0], [0], str.length);

chars[0..str.length] = str;
assert(false, chars[0..str.length]);
}

What am I missing here?



Re: @nogc deduction for templated functions

2017-11-18 Thread David Zhang via Digitalmars-d-learn
Huh, I think I did something weird. It compiles now, and I don't 
know why. Thanks for your answers.


@nogc deduction for templated functions

2017-11-18 Thread David Zhang via Digitalmars-d-learn

Hi,

Is there a way for a templated function to deduce or apply the 
@safe/@nogc attributes automaticaly? I feel like I remember dmd 
doing so at one point, but it doesn't appear to work anymore. In 
particular, I need to call a function belonging to a templated 
type, but do not know what attributes are applied.


eg.

void func(T)(T t)
{
//Don't know if safe or nogc
t.someFunc();
}

Thanks.


Re: Getting the size of a type tuple

2017-09-21 Thread David Zhang via Digitalmars-d-learn

On Thursday, 21 September 2017 at 19:49:14 UTC, ag0aep6g wrote:
I don't have a one-liner, but here are some other solutions 
that might be interesting. None of them is particularly pretty, 
though.


1) Recursive template: 

2) Using the std library: 

3) Declaring a packed struct in a function literal that gets 
immediately called: 


I think the recursive one looks best, but I agree. None of them 
look particularly good.


Getting the size of a type tuple

2017-09-21 Thread David Zhang via Digitalmars-d-learn

Given the function F, where: F(Args...)(Args args) { ... }

How can I statically determine the size of the argument list in 
bytes?


Preferably, I would like a one-liner. However, std.algorithm 
doesn't seem to support tuples, or `Args.each!(T => 
T.sizeof).sum` would work.


For the moment, I've settled on using a helper function:

size_t size(Args...)()
{
size_t size;
foreach(Arg; Args)
size += Arg.sizeof;
return size;
}

But it's a bit clunky. Is there a more idiomatic way to do this?

Thanks


Re: Propagating constness through function results

2017-09-17 Thread David Zhang via Digitalmars-d-learn

Nevermind! I rediscovered the `inout`attribute.

Though if I may say so, I have no idea how `inout` is supposed to 
indicate "whatever the constness of a".




Re: Propagating constness through function results

2017-09-17 Thread David Zhang via Digitalmars-d-learn

On Sunday, 17 September 2017 at 21:18:08 UTC, David  Zhang wrote:

Hi,

I have a class `Image`, and I have a function called 
`getSubImage(Rect bounds)`. What I can't figure out is how to 
get the result of `getSubImage()` to take on the constness of 
the backing image.


ie.
//The Image class is really just a view over a buffer 
that's managed elsewhere

const(Image).getSubImage(...) -> const(Image)

Image.getSubImage(...) -> Image

I tried to do this with `inout`, but that requires that a 
parameter in the function be `inout`. I don't suppose I could 
somehow declare `this` to be inout?


Thanks


I am aware that you can duplicate the method, but it seems a bit 
unwieldy and excessive.


Propagating constness through function results

2017-09-17 Thread David Zhang via Digitalmars-d-learn

Hi,

I have a class `Image`, and I have a function called 
`getSubImage(Rect bounds)`. What I can't figure out is how to get 
the result of `getSubImage()` to take on the constness of the 
backing image.


ie.
//The Image class is really just a view over a buffer that's 
managed elsewhere

const(Image).getSubImage(...) -> const(Image)

Image.getSubImage(...) -> Image

I tried to do this with `inout`, but that requires that a 
parameter in the function be `inout`. I don't suppose I could 
somehow declare `this` to be inout?


Thanks


Re: DLL loading behaviors and pragma(lib)

2017-08-11 Thread David Zhang via Digitalmars-d-learn

On Friday, 11 August 2017 at 04:50:48 UTC, rikki cattermole wrote:

On 11/08/2017 12:18 AM, David Zhang wrote:
I've been working on getting OpenGL to load on windows without 
a library, and encountered something curious;


Context creation fails when I try to use the function pointer 
retrieved through GetProcAddress, but works just fine with the 
statically linked version provided through 
core.sys.windows.wingdi.d.


This may be a stupid question, but why is this?

Thanks.


Odd.

Just to confirm your wglGetProcAddress, is 
extern(Windows/System)?

And it is non-null after being loaded?


Yes.


DLL loading behaviors and pragma(lib)

2017-08-10 Thread David Zhang via Digitalmars-d-learn
I've been working on getting OpenGL to load on windows without a 
library, and encountered something curious;


Context creation fails when I try to use the function pointer 
retrieved through GetProcAddress, but works just fine with the 
statically linked version provided through 
core.sys.windows.wingdi.d.


This may be a stupid question, but why is this?

Thanks.


Re: Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-22 Thread David Zhang via Digitalmars-d-learn

On Sunday, 21 May 2017 at 10:03:58 UTC, Nicholas Wilson wrote:
As in the function signature of the function you call `ok` or 
`error` in.


Result!(int, SomeEnum) myfunc(bool foo)
{
if(!foo)
return ok(42);
else
return error(SomeEnum.fooHappened);
}

should work.


This is what I've got right now.

--- [module 1]
struct Result(OkType, ErrType)
{
this(OkType ok) pure nothrow
{
isOk = true;
okPayload = ok;
}

this(ErrType error) pure nothrow
{
isOk = false;
errorPayload = error;
}

bool isOk;

union
{
OkType okPayload;
ErrType errorPayload;
}
}

auto ok(T, E)(T payload) { return Result!(T, E)(payload); }
auto error(T, E)(T payload) { return Result!(T, E)(payload); }

--- [module 2]

Result!(string, int) fn(bool shouldErr) {
if (!shouldErr)
return ok("No problem");
return error(0);
}

---

But it can't infer the second parameter.
"template result.ok cannot deduce function from argument types 
!()(string)"




Re: Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-21 Thread David Zhang via Digitalmars-d-learn

On Sunday, 21 May 2017 at 09:37:46 UTC, Nicholas Wilson wrote:

On Sunday, 21 May 2017 at 09:29:40 UTC, David  Zhang wrote:
Well then it becomes
 Result!(T, E) ok(T,E) (T t) { return Result(t); }
 Result!(T, E) error(T,E)(E e) { return Result(e); }

and then provided it can be inferred (e.g. from the function 
signature)

it will still work.


But how would it be inferred? Like the `ok` function, `T` could 
be inferred, but E? I'm not sure I understand. If you have to 
specify the types every time, it kinda defeats the purpose. With 
the function signature as it is, you'd have to specify the type 
of the other type (e.g. you'd need to specify E for `ok()`).


Re: Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-21 Thread David Zhang via Digitalmars-d-learn

On Sunday, 21 May 2017 at 09:15:56 UTC, Nicholas Wilson wrote:

have free functions

 Result!(T, ErrorEnum) ok(T)(T t) { return Result(t); }
 Result!(T, ErrorEnum) error(T)(ErrorEnum e) { return 
Result(e); }


then go

if (!foo)
return ok(42);
else
return error(Error.fooHappened);


Ah, I think you misread. ErrorEnum is a template type, like `T`. 
There's no ErrorEnum enum specified.


Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-21 Thread David Zhang via Digitalmars-d-learn

Hi,

I was reading a bit about this in Rust, and their enum type. I 
was wondering if this is replicate-able in D. What I've got right 
now is rather clunky, and involves using


 `typeof(return).ok` and `typeof(return).error)`.

While that's not too bad, it does involve a lot more typing, and 
thus more area for human error.


If you're not familiar with the Result and Option types, it 
allows you to do something like this:


---
Result!(string, ErrorEnum) someFunction(...)
{
return Ok("Hello!");
}

Result!(string, ErrorEnum) someFunction2(...)
{
return Error(ErrorEnum.dummyError);
}
---

I'm not entirely sure it's possible... but I figured I might give 
it a try.


Re: Converting a string[] to char**

2017-05-09 Thread David Zhang via Digitalmars-d-learn

On Tuesday, 9 May 2017 at 07:59:19 UTC, Stanislav Blinov wrote:

On Tuesday, 9 May 2017 at 07:50:33 UTC, David  Zhang wrote:

If indeed there is no way to avoid allocation, do the 
allocations have to remain 'alive' for the duration of the 
instance? Or can I deallocate immediately afterwards? I can't 
seem to find it in the Vulkan spec.


2.3.1. Object Lifetime:

Application-owned memory is immediately consumed by any Vulkan 
command it is passed into. The application can alter or free 
this memory as soon as the commands that consume it have 
returned.


I see, thanks.


Re: Converting a string[] to char**

2017-05-09 Thread David Zhang via Digitalmars-d-learn

On Tuesday, 9 May 2017 at 05:52:28 UTC, Mike Parker wrote:

On Tuesday, 9 May 2017 at 05:38:24 UTC, ag0aep6g wrote:

You have to create a new array of pointers. As rikki 
cattermole has pointed out, you also have to null-terminate 
the individual strings, and pass the amount of pointers in a 
separate parameter.



import std.algorithm.iteration: map;
import std.array: array;
import std.conv: to;
import std.string: toStringz;

string[] strs = ["foo", "bar", "baz"];

/* convert string[] to char*[]: */
immutable(char)*[] chptrs = strs.map!toStringz.array;

immutable(char)** ppEnabledLayerNames = chptrs.ptr;
uint enabledLayerCount = chptrs.length.to!uint;



Although, if it's known that the array was populated with 
literals, toStringz isn't needed. String literals are 
automatically nul terminated.


Thanks for all your answers.

The strings are all predefined statically for the moment, with a 
'\0' character at the end.


I take from this that there's no way to avoid allocating then? I 
had hoped... :(


If indeed there is no way to avoid allocation, do the allocations 
have to remain 'alive' for the duration of the instance? Or can I 
deallocate immediately afterwards? I can't seem to find it in the 
Vulkan spec.




Converting a string[] to char**

2017-05-08 Thread David Zhang via Digitalmars-d-learn

Hi,

I'm playing around with Vulkan, and part of its initialization 
code calls for an array of strings as char**. I've tried casting 
directly (cast(char**)) and breaking it down into an array of 
char*s (char*[]) before getting the pointer to its first element 
([0]). It provides the correct type, but Vulkan rejects it. Is 
there a standard way of doing this?


I'm trying to set the ppEnabledExtensionNames member of 
VkInstanceCreateInfo.


Regards,
David


Implementing casting outside of the target struct

2017-03-16 Thread David Zhang via Digitalmars-d-learn

Hi,

I have two structs and want to cast between them. The cast is 
generalizable, so I want to keep it outside of the structs 
themselves (I'll be adding more later). How can I do this? I've 
tried the following so far:


struct Event {
EventID id;
ubyte[32 - EventID.sizeof] payload;
}

struct WindowCreateEvent {
enum id = EventID.windowCreate;

version (Windows) {
import core.sys.windows.windows;
HWND windowHandle;
}
}

T opCast(T, K)(auto ref K e) {
import core.stdc.string: memcpy;

auto result = Event(e.id);

memcpy(result.payload.ptr, cast(void*) & e, K.sizeof);

return result;
}

The compiler seems to want to convert the two structs bit-by-bit. 
How can I make it use the module-scoped override? Thanks.


Re: Declaring interfaces with a constructor

2017-03-14 Thread David Zhang via Digitalmars-d-learn

On Tuesday, 14 March 2017 at 02:14:53 UTC, evilrat wrote:

like this?
--
[snip]
-

there is also way to do this using templates and duck typing, I 
think it will be more idiomatic way since ranges and stuff 
heavily use it to provide such generalism, though just like you 
say, I would prefer to have strict interface for such use 
case...


Yeah, that's the idea. Though I just thought of a possibility 
using an isPublicInterface template. Is that what you meant by 
templates and duck typing?


Re: Declaring interfaces with a constructor

2017-03-13 Thread David Zhang via Digitalmars-d-learn

On Monday, 13 March 2017 at 17:52:09 UTC, XavierAP wrote:

On Monday, 13 March 2017 at 02:15:21 UTC, David  Zhang wrote:
What it says on the tin. Is there a way to create interfaces 
with a constructor or must I use an abstract class.


What do you want to do in your constructor? I can't think of 
anything that wouldn't change some state, either of the class 
(but interfaces aren't allowed to have fields either, precisely 
because they may not have state), or the global state 
(worse...). Just curious.


Additionally, is there a way to force the linker to link a 
function in a class without an implementation with another 
that does have an implementation?


I'm not sure if you mean the same as generating "interface 
files"?

[1] https://dlang.org/dmd-windows.html#interface-files


Basically, I want to define a common interface for a group of 
platform-specific classes, except that they should ideally also 
share constructor parameters. What I want to do is then alias 
them to a common name, selecting the implementation for the 
target platform at compile time.


Declaring interfaces with a constructor

2017-03-12 Thread David Zhang via Digitalmars-d-learn
What it says on the tin. Is there a way to create interfaces with 
a constructor or must I use an abstract class.


Additionally, is there a way to force the linker to link a 
function in a class without an implementation with another that 
does have an implementation?


i.e.

---
//module a;
class Foo {
void fun();
}

import b: Foo;

//module b;
class Foo {
void fun() { import std.stdio; writeln("!"); }
}
---

Or something like this? Thanks.


Re: Declaring constant references in struct members

2017-02-15 Thread David Zhang via Digitalmars-d-learn
On Thursday, 16 February 2017 at 00:49:45 UTC, Adam D. Ruppe 
wrote:
On Thursday, 16 February 2017 at 00:43:30 UTC, David  Zhang 
wrote:

struct S {
O object;
}


import std.typecons;

Rebindable!O object;

http://dpldocs.info/experimental-docs/std.typecons.Rebindable.html


Is there a similar mechanism for one struct holding another? 
Otherwise, you get a cannot modify X with immutable members error.


eg:

struct A {
B b;
}

struct B {
const size_t something;
}

A a = A(B(16));

//attempt to replace a.b with new B
a.b = B(32); //error: cannot modify struct a.b B with immutable 
members




Declaring constant references in struct members

2017-02-15 Thread David Zhang via Digitalmars-d-learn

Hi,

Say I have a struct S that holds a reference to an object O. Is 
there a way to express that I want to be able to change the 
reference, but not what the reference points to? Thanks.


struct S {
O object;
}

class O {
size_t things.
}



Re: Creating an array of immutable objects

2017-02-14 Thread David Zhang via Digitalmars-d-learn
Thanks for your answers. Out of curiosity though, how could 
something like this be done with classes instead?


Creating an array of immutable objects

2017-02-13 Thread David Zhang via Digitalmars-d-learn

Hi,

I have a struct with two immutable members, and I want to make an 
array of them. How do I to this? I'm using allocators for this.


string[] paths;

struct FileDesc {
immutable string path;
immutable uint index;
}

_fileDesc = /*something*/;

You can't use alloc.makeArray because it requires a range with 
which to initialize the array, and while I can produce an array 
of paths, I don't know how to merge both a range of paths and 
indices. Lockstep doesn't work.


I also tried using emplace and an allocated byte array, but it 
gave me random values and was (I think) unnecessarily 
complicated. What am I missing?


How does cast(SomeObj) (cast(void*) ptrFromC) work?

2017-01-25 Thread David Zhang via Digitalmars-d-learn
I was trying to figure out why calling an object's function from 
a wndProc that modified the object's state didn't actually change 
anything. Wrapping the GetWindowLongPtr in a cast(void*) seems to 
make it work. What am I missing about this? I though that object 
references were really just pointers with special 
restrictions/behaviors?


Old:
window = cast(Win32Window) GetWindowLongPtr(hwnd, 
GWLP_USERDATA);


New:
window = cast(Win32Window) (cast(void*) 
GetWindowLongPtr(hwnd, GWLP_USERDATA));


Object function cannot change member when called from callback?

2017-01-24 Thread David Zhang via Digitalmars-d-learn
So I have a window (Windows), and my wndProc is basically the 
same as the one on the windows guides. However, even though 
WM_CLOSE gets passed (and I can use if(msg == WM_CLOSE)), I can't 
seem to set my shouldClose flag. I've confirmed that I still get 
the event within my processMessage method. SO my question is 
this: what is going on, and how can I make it work?


extern (Windows) LRESULT wndProc(HWND hwnd, uint msg, WPARAM wp, 
LPARAM lp) nothrow {

import std.stdio;
import std.exception;

Win32Window* window;

if (msg == WM_NCCREATE)
window = setWindowPtr(hwnd, lp);
else
window = getWindowPtr(hwnd);

if (window !is null)
return window.processMessage(msg, wp, lp);
else
return DefWindowProc(hwnd, msg, wp, lp);
}

Window {
//--- other stuff ---//

LRESULT processMessage(uint msg, WPARAM wp, LPARAM lp) 
nothrow {

switch (msg) {
case WM_CLOSE:
_shouldClose = true; //tests as true here, but has no 
effect after method exits
assumeWontThrow(writeln("close request received")); 
//this works

return 0;
default:
return DefWindowProc(_hwnd, msg, wp, lp);
}
}
}

Sidenote, I can't build this with ldc2 for some reason: "cannot 
open input file 'kernel32.lib'". dmd seems to work just fine.


Re: Accessing a function within an object's superclass from the outside

2017-01-14 Thread David Zhang via Digitalmars-d-learn

On Saturday, 14 January 2017 at 22:17:23 UTC, ketmar wrote:

class ClassB: ClassA {
  alias fun = super.fun;
  override void fun(uint a) {}
}


I tried that, but it seems to think I mean to override 
super.fun(uint) instead of super.fun(uint, float).


Looking at my code again, one of them is templated with a range 
interface. I think that might be the problem, though I can't 
figure out how to fix it. Wrapping the alias in a template block 
doesn't seem to do it.


Accessing a function within an object's superclass from the outside

2017-01-14 Thread David Zhang via Digitalmars-d-learn

Hello,

Say I have a class, and it overrides a function from its 
superclass. However, the superclass has two overloaded versions 
of the same function. My intent is to override only one of the 
functions, but the second is rendered inaccessible from outside 
of the class. How can I make the overloaded function visible?


ie:

class ClassA {
void fun(uint a) {}
void fun(uint a, float b) {}
}

class ClassB: ClassA {
void fun(uint a) {}
}

ca.fun(a);   //ok
ca.fun(a, b);//ok
cb.fun(a);   //ok
cb.fun(a, b);//function fun not callable with uint and float

I seem to remember something about using aliases to fix this, but 
I can't find anything about it either way.


Re: Unittest hangs on completion

2016-12-30 Thread David Zhang via Digitalmars-d-learn
On Saturday, 31 December 2016 at 02:36:01 UTC, rikki cattermole 
wrote:

No, my understand is thus:

 next = current.next;
 theAllocator.dispose(current);

When current is deallocated, current is pointing to free'd 
memory.
After that point it should be segfaulting when you try to 
access it *I think*.


Huh, alright. I see what you mean. I'll keep this in mind.


Re: Unittest hangs on completion

2016-12-30 Thread David Zhang via Digitalmars-d-learn
On Saturday, 31 December 2016 at 02:03:07 UTC, rikki cattermole 
wrote:

As it should, current is never reassigned.
You only need one var, next. Of course I didn't read the entire 
thread chain so, I'm probably missing something.


import std.experimental.allocator;

void main() {
struct S { S* next; }
S* _foo;
foreach (e; 0 .. 10)
_foo = theAllocator.make!S(_foo);
S* next;

next = _foo;
while(next !is null) {
auto nextT = next.next;
theAllocator.dispose(next);
next = nextT;
}
}


Thanks for your response. So next is never null, and thus there 
is an infinite loop, correct? If so, why does dub indicate that 
all tests are complete?


Re: Unittest hangs on completion

2016-12-30 Thread David Zhang via Digitalmars-d-learn
Extracting everything into a main() also causes the application 
to hang.


ie:

struct S
{
S* next;
}

S* _foo;
foreach (e; 0 .. 10)
_foo = theAllocator.make!S(_foo);

S* next, current;
next = current = _foo;
while (next)
{
next = current.next;
theAllocator.dispose(current);
}




Re: Unittest hangs on completion

2016-12-30 Thread David Zhang via Digitalmars-d-learn
On Friday, 30 December 2016 at 22:42:07 UTC, Steven Schveighoffer 
wrote:
What is actually happening is that the D main function returns. 
Then the D runtime tears down everything, including joining all 
threads, running all module static dtors, terminating the GC, 
etc.


Then it returns to the OS the exit code.

So it's likely somewhere in there that it's hanging.

-Steve


I've tried manually reducing the code to find the problem. This 
is what I've got. I'm not sure how to reduce it further.


class Foo {
~this() {
S* next, current;
next = current = _foo;
while (next) {
next = current.next;
theAllocator.dispose(current);
}
}

void insert(Range)(Range range) {
foreach (e; range)
_foo = theAllocator.make!S(_foo);
}

S* _foo;

struct S { S* next; }
}

unittest {
auto list = new Foo();

list.insert([1, 2, 3, 4]);
}



Re: Unittest hangs on completion

2016-12-30 Thread David Zhang via Digitalmars-d-learn

On Friday, 30 December 2016 at 20:59:30 UTC, Seb wrote:

On Friday, 30 December 2016 at 18:03:44 UTC, David  Zhang wrote:
On Friday, 30 December 2016 at 14:12:35 UTC, Steven 
Schveighoffer wrote:

[snip]
It depends on what is actually hanging the process. If it's 
something in your code base only, then nobody else would be 
seeing it.


-Steve


So, what should I do with it? I'd submit a bug report, but I 
don't know how to isolate the bug, and thus where to submit 
it. Really, I'd just be happy knowing if it's my code or not.


Dustmite (https://github.com/CyberShadow/DustMite) is your 
friend!
Specifically with a timeout command (e.g. 
https://github.com/CyberShadow/DustMite/wiki/Running-commands-with-a-timeout) and checking whether your reduced code is still timing out (exit code of timeout is 124).
If you set it to sth. reasonable (e.g. 10s) and use multiple 
threads (e.g. -j32) it shouldn't take that long to have a 
reduced code example.


There wouldn't happen to be an alternative on windows without 
installing cygwin would there? I don't have access to a linux 
machine at the moment.


@Steven, the process hangs after the "All unit tests have been 
successfully", after which the process is supposed to exit 
immediately.


--
Running .\bin\__test__library__.exe
All unit tests have been run successfully.
^C
--


Re: Unittest hangs on completion

2016-12-30 Thread David Zhang via Digitalmars-d-learn
On Friday, 30 December 2016 at 14:12:35 UTC, Steven Schveighoffer 
wrote:

[snip]
It depends on what is actually hanging the process. If it's 
something in your code base only, then nobody else would be 
seeing it.


-Steve


So, what should I do with it? I'd submit a bug report, but I 
don't know how to isolate the bug, and thus where to submit it. 
Really, I'd just be happy knowing if it's my code or not.


Re: Unittest hangs on completion

2016-12-29 Thread David Zhang via Digitalmars-d-learn
On Friday, 30 December 2016 at 01:25:50 UTC, Steven Schveighoffer 
wrote:

Looks like that comes from here:

https://github.com/dlang/dub/blob/master/source/dub/dub.d#L577

I have serious doubts that this is the correct way to run 
tests, as share ctors are supposed to have run BEFORE unit 
tests are allowed to. It's quite possible (and likely) that 
unit tests are running before critical other shared ctors have 
completed, which is why something isn't working.


In any case, it looks like the unit tests have run, and run 
successfully, and then main has run, and then it's the teardown 
of the runtime that's hanging.


I'm not 100% certain, because I don't know exactly how this 
code comes into play -- it's a string in this file.


-Steve


Huh, shouldn't this problem have manifested itself earlier then? 
Why only now? I don't remember this happening previously. At the 
very least I'm pretty sure I first encountered it last week. 
Unless something in DMD was patched? But then there'd be no way 
I'm the only one encountering this problem, and there don't 
appear to be any issues on github's tracker.




Re: Unittest hangs on completion

2016-12-29 Thread David Zhang via Digitalmars-d-learn
On Friday, 30 December 2016 at 00:44:50 UTC, Steven Schveighoffer 
wrote:


Where does the "All unit tests have been completed 
successfully." message come from? That's not standard D, which 
prints nothing.


-Steve


I should have mentioned that I use dub then, shouldn't I? Anyway, 
this is what I get:


C:\Users\David\Projects\weave>dub test
Generating test runner configuration '__test__library__' for 
'library' (library).

Performing "unittest" build using dmd for x86.
weave ~master: building configuration "__test__library__"...
Linking...
Running .\bin\__test__library__.exe
All unit tests have been run successfully.


Re: Unittest hangs on completion

2016-12-29 Thread David Zhang via Digitalmars-d-learn

On Thursday, 29 December 2016 at 20:50:54 UTC, David  Zhang wrote:
On Thursday, 29 December 2016 at 20:33:33 UTC, Stefan Koch 
wrote:
It would be very helpful if you could provide example code 
that triggers that behavior.


I'd love to, but I'm not actually sure just what it is that 
breaks it. I can provide the git repo for one of them though 
though:


https://gitlab.com/Straivers/Weave
https://gitlab.com/Straivers/Weave.git


Ok, so after further fiddling, it seems to originate from here:

[from the list class]

@safe unittest {
class A {
int foo;
}

auto list = new List!A();
list ~= [new A, new A, new A];

assert(list.findElement(null).result == null);
}

However, commenting it out, and replacing it with another block 
(the test immediately below it, causes it to hang too, or error 
out and crash without any error message.




Re: Unittest hangs on completion

2016-12-29 Thread David Zhang via Digitalmars-d-learn

On Thursday, 29 December 2016 at 20:33:33 UTC, Stefan Koch wrote:
It would be very helpful if you could provide example code that 
triggers that behavior.


I'd love to, but I'm not actually sure just what it is that 
breaks it. I can provide the git repo for one of them though 
though:


https://gitlab.com/Straivers/Weave
https://gitlab.com/Straivers/Weave.git


Unittest hangs on completion

2016-12-29 Thread David Zhang via Digitalmars-d-learn

Hi,

I've noticed recently, that whenever I unittest, it program hangs 
either at the very end, or right before they start. When using 
vanilla unit tests, the program appears to hang after the "All 
unit tests have been completed successfully." message, and I have 
to force to program to exit. However, when I use unit-threaded 
for my unit testing, it gets to the "Running unit tests in dirs 
["."]" and then refuses to do anything more. Strangely enough, 
sometimes commenting out one or two tests seems to fix the issue 
with unit-threaded, only to resurface when I write a new test. 
Just what is going on?


Re: Allocating a class within another class during object init w/o passing in an allocator

2016-12-16 Thread David Zhang via Digitalmars-d-learn
I haven't considered alignment here. I'm not sure if you have 
to.


I though all classes were aligned to sizeof(size_t) boundaries? 
Wouldn't it then just be


align(sizeof(size_t)) byte[__traits(classInstanceSize, 
SomeClass)] scStorage;


Re: Allocating a class within another class during object init w/o passing in an allocator

2016-12-15 Thread David Zhang via Digitalmars-d-learn

On Thursday, 15 December 2016 at 21:08:51 UTC, ag0aep6g wrote:

On 12/15/2016 09:51 PM, David Zhang wrote:

However, it leaves me with another question, how
much (if any) space would the static array require from the 
class?


Depends on SomeClass. The array's size is just the value of 
__traits(classInstanceSize, SomeClass). There's no overhead.


You can print such stuff at compile time with pragma(msg, ...):


pragma(msg, __traits(classInstanceSize, SomeClass));
pragma(msg, Foo.scStorage.sizeof); /* same */



So the size of Foo would be the size of SomeClass plus members? 
ie. Is the size of the array stored too?


Re: Allocating a class within another class during object init w/o passing in an allocator

2016-12-15 Thread David Zhang via Digitalmars-d-learn
Thank you for your responses. Visitor, I don't want any reference 
to an allocator within the class if I can avoid it. ag0aep6g, 
thanks! That's what I was looking for. However, it leaves me with 
another question, how much (if any) space would the static array 
require from the class? It's not a strict necessity for me, but 
I'm curious.


Allocating a class within another class during object init w/o passing in an allocator

2016-12-15 Thread David Zhang via Digitalmars-d-learn

Hello,

It is my understanding that a class can have a struct as one of 
its members, and it will be allocated in-line with the rest of 
the class' members. My question is this; how might I be able to 
do this with another class? I want to be able to allocate Foo 
using std.experimental.allocator without having to pass in a 
reference to the actual allocator. Thanks.


eg:
class SomeClass {}

class Foo {
this(IAllocator alloc) {
sc = alloc.make!SomeClass;
this.alloc = alloc
}

~this() {
alloc.dispose(sc);
}

size_t something;
SomeClass sc;
IAllocator alloc
}

auto foo = alloc.make!Foo(alloc);

vs.

struct SomeStruct {}

class Foo {
this() {
ss = SomeStruct (...);
}

size_t something;
SomeStruct ss;
}

auto foo = alloc.make!Foo;