Re: Handling different types gracefully
Roderick Gibson: Variant is a possiblity. How is the performance with large containers of these, since these structures will likely hold the majority of the data in the game? You probably have to benchmark yourself. (But I have suggested an Algebraic). Bye, bearophile
Re: C standard libraries
It is in core.stdc. For example: import core.stdc.stdio; // import core.stdc.stdlib;// etc. Thanks! I'm confused why that module isn't mentioned in the library reference page. What's the difference between core.stdc and std.c? The docs do refer to core.stdc, though std.c.stdio in Phobos' source just imports core.stdc.stdio. The duplication seems a bit weird, and I'm wondering if one method is deprecated or migth be removed in the future.
Re: Handling different types gracefully
On Monday, 1 July 2013 at 12:16:50 UTC, bearophile wrote: Roderick Gibson: auto entities = new Entities(); auto entity_id = entities.createEntity(); entities.addComponent!(position)(entity_id, pos); entities.addComponent!(movement)(entity_id, mov); entities.addComponent!(collision)(entity_id, col); auto physics_data = entities.getEntitiesWithComponents!(position, movement, collision)(); The two big requirements are some kind of regular, queryable structure to hold the components (of different types), and the ability to filter by type. Is anything like that remotely possible? If the possible types are know, then there's std.variant.Algebraic, otherwise there is a free Variant or VariantN. They are not perfect, but maybe they are good enough for you. Bye, bearophile Variant is a possiblity. How is the performance with large containers of these, since these structures will likely hold the majority of the data in the game? Waiting for multiple "alias this" ?? And opDispatch to respond to unimplemented components. I'm not sure what you mean by this.
Re: Template constraints and opAdd
On Tuesday, 2 July 2013 at 01:39:22 UTC, anonymous wrote: On Tuesday, 2 July 2013 at 01:24:18 UTC, bearophile wrote: anonymous: You can't overload non-templates with templates, I think it was recently fixed in Git. It's still buggy then, since adding the empty parentheses makes the error go away. ... or maybe my checkout wasn't up to date ;)
Re: Template constraints and opAdd
On Tuesday, 2 July 2013 at 01:24:18 UTC, bearophile wrote: anonymous: You can't overload non-templates with templates, I think it was recently fixed in Git. It's still buggy then, since adding the empty parentheses makes the error go away.
Re: Template constraints and opAdd
John: Mass!(T,S) opBinary(alias operator)(Mass!(T,S) other) { Mass!(T,S) opBinary(alias operator, O)(Mass!(O,S) other) if (!is(O == T)) { Isn't operator better as string? -- anonymous: You can't overload non-templates with templates, I think it was recently fixed in Git. Bye, bearophile
Re: Template constraints and opAdd
On Monday, 1 July 2013 at 23:36:27 UTC, John wrote: struct Mass(T, S) { ... Mass!(T,S) opAdd(Mass!(T,S) other) { You can't overload non-templates with templates, yet. It's supposed to work, but not implemented. The workaround is simple enough: Mass!(T,S) opAdd()(Mass!(T,S) other) { // note the () after opAdd return op!"+"(other); } Mass!(O,S) opAdd(O)(Mass!(O,S) other) if (typeof(O) != typeof(T)) { That constraint should be: if (!is(O == T)) return op!"+"(other); } ... }
Re: Template constraints and opAdd
On Tuesday, 2 July 2013 at 00:01:48 UTC, bearophile wrote: John: Mass!(T,S) opAdd(Mass!(T,S) other) { If you are using D2 then don't use opAdd, use opBinary: http://dlang.org/operatoroverloading.html#Binary Bye, bearophile Thanks, I switched over to using the new function and after fiddling with the functions I came up with a pair that seem to work. Mass!(T,S) opBinary(alias operator)(Mass!(T,S) other) { Mass!(T,S) opBinary(alias operator, O)(Mass!(O,S) other) if (!is(O == T)) {
opDispatch and UFCS
import std.conv, std.stdio, std.algorithm; struct S { void opDispatch(string s, T...)(T t) if (s.startsWith("foo")) { writeln(s); } } void main() { S s; s.foo(); auto p = s.to!string(); // Error: s.opDispatch!("to") isn't a template } Should the constraint on opDispatch allow the UFCS "to" call on S?
Re: Template constraints and opAdd
John: Mass!(T,S) opAdd(Mass!(T,S) other) { If you are using D2 then don't use opAdd, use opBinary: http://dlang.org/operatoroverloading.html#Binary Bye, bearophile
Template constraints and opAdd
I'm getting conflicting templates in this struct and I'm not sure how. I specifically excluded the second definition of opAdd from using type T in place of O but the compiler still tells me I'm getting template conflicts. Compiler error using Mass!(double,string): Error: template mass.Mass!(double,string).Mass.opAdd(O) if ((typeof(O)) != (typeof(T))) conflicts with function mass.Mass!(double,string).Mass.opAdd at src\mass.d(38) I have a struct: struct Mass(T, S) { ... Mass!(T,S) opAdd(Mass!(T,S) other) { return op!"+"(other); } Mass!(O,S) opAdd(O)(Mass!(O,S) other) if (typeof(O) != typeof(T)) { return op!"+"(other); } ... } And I'm trying to do something like: Mass!(double,string) first = ... Mass!(double,string) second = ... auto result = first + second; I'm trying to add a Mass!(double,string) + Mass!(double,string), which should mean the second template gets ignored since T=double and O=double. What am I missing?
Re: Eponymous template with full template syntax
On 07/01/2013 02:10 PM, monarch_dodra wrote: >> That is confusing. > > UFCS construction: Yes. I *think* I did not know it but I can't be sure. :) struct S { int i; } void main() { static assert (S(42) == 42.S); } It works with 2.063 (v2.064-devel-a1a1537 too). > The rest, not so much: > > The idea is that once a template is "eponymous", it *fully* becomes the > eponymous function/type/value (s). Every other function, regardless of > public/private*, simply seizes to exist to the outside world. You can't > make a "qualified" call to an eponymous template, because the > "qualification" is already the call. A single definition with the same name makes it an eponymous template. I used to think that the template should also have a single definition. So, currently other definitions act as implementation details of the template. The following template sees the local S, not the module-level one: struct S { int[10] i; } template epo(T) { size_t epo() { return S.sizeof; // <-- epo.S, not .S } struct S { int i; } double foo() { return 1.5; } } void main() { assert(epo!int() == int.sizeof); // <-- yes, epo.S mixin epo!int; assert(foo() == 1.5); } Also note that mixing in the template is still possible but it is an orthogonal feature anyway. Ali
Re: memcpy in D
On 07/01/2013 03:23 PM, Tyro[17] wrote: > So just to confirm my understanding: Because the address at memory is > casted to ushort* in defining base, every iteration of the foreach loop > advances the pointer two bytes into the array? Yes. The incerement operator on a pointer advances the pointer to point at the next element. Automatic! :) Same with arithmetic operations. (ptr + 1) is the address value that points at the next element. Ali
Re: memcpy in D
I'd just like to say thanks for your suggestions and quite complete solutions. I particularly liked the alternate implementation presented by Marco. I must admit that I did not understand what was happening at first. So just to confirm my understanding: Because the address at memory is casted to ushort* in defining base, every iteration of the foreach loop advances the pointer two bytes into the array? Thanks, Andrew
Re: .Exe file how to embed in resource after start program
Dne 1.7.2013 23:03, Ali GOREN napsal(a): On Monday, 1 July 2013 at 20:11:40 UTC, Ali Çehreli wrote: On 07/01/2013 12:28 PM, Ali GOREN wrote: > Sorry for my bad english. Please don't say that. :) Thank you very much for writing in English so that we can understand you. I don't have an answer to your question though... :-/ Ali Hmm thank you very much :) i want to embed because high security program :( Hi, one way, not necessarily the optimal one, that works in Windows: - save the exe as a string in a file, like: enum prog = '...'; and compile it to your wrapping program - 1) run the wrapping program, write the prog to disk and call CreateProcessEx (it requires file in the filesystem) - 2) run the wrapping program, memory map the prog and then try to follow this guide at StackOverflow (the one with 21 upvotes) http://stackoverflow.com/questions/305203/createprocess-from-memory-buffer Both approaches have their pros and cons and you should tread carefully, especially if you say that this should be about high security... Regards, Martin
Re: Eponymous template with full template syntax
On Monday, 1 July 2013 at 20:28:28 UTC, Ali Çehreli wrote: On 07/01/2013 12:03 PM, Maxim Fomin wrote: > I think that this probably worked as early as in the end of 2011 but I > can be wrong as don't remember exactly. To answer Jonathan's question as well, it must have worked because I see it in code that is definitely tested when it was written. > It seems that dmd recognizes isSmall!int.isSmall as potential UFCS > property, converts isSmall!int to bool and tries to issue call > isSmall(bool) and fails, because that template does not define any > function. That explains it. :) Let's play with it a little: import std.stdio; template isSmall(T) { enum isSmall = (T.sizeof < 12345); struct S { T m; } } struct S { int[10] i; } void main() { writeln(isSmall!int); writeln(isSmall!int.S.init); writeln(isSmall!int.S); } First of all, apparently a template can include a definition with the same name but I still cannot type isSmall!int.isSmall. I guess the above is still an eponymous template and isSmall!int still means isSmall!int.isSmall. Now guess what the last two lines print. :) isSmall!int.S is *not* the S that is included in the template! Here is the output: true S([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) S([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) The last line is actually an anonymous struct object of type S (the S that is defined at module level). I though UFCS wasn't possible with constructors? *That* very usecase is one of the reasons why. Shouldn't that be an accepts-invalid? That is confusing. UFCS construction: Yes. The rest, not so much: The idea is that once a template is "eponymous", it *fully* becomes the eponymous function/type/value (s). Every other function, regardless of public/private*, simply seizes to exist to the outside world. You can't make a "qualified" call to an eponymous template, because the "qualification" is already the call. Long story short, it's not mix and match: Either you have a normal template, or you have an something eponymous, not a bit of both: *What qualifies for eponymous template is kind of "buggy", since what actually qualifies is not exactly what the spec says. Still, *once* something is considered "qualified" by the implementation, then it is fully eponymous.
Re: .Exe file how to embed in resource after start program
On Monday, 1 July 2013 at 20:11:40 UTC, Ali Çehreli wrote: On 07/01/2013 12:28 PM, Ali GOREN wrote: > Sorry for my bad english. Please don't say that. :) Thank you very much for writing in English so that we can understand you. I don't have an answer to your question though... :-/ Ali Hmm thank you very much :) i want to embed because high security program :(
Re: Is this a bug in the concurrency lib or am i using it incorrectly?
On Monday, 1 July 2013 at 19:15:45 UTC, Gary Willoughby wrote: If you remove the the try..catch you will notice that OwnerTerminated is thrown, if this is the intended behaviour, I don't know. Probably is, because this would be a pretty obvious bug. Ah right, so i guess the main thread is finishing and throwing the exception to writer before sender has sent anything? An easy way of dealing with this would be to have main wait for a message from another thread telling it to terminate. My way of imagining threads in the std.concurrency model (for some reason it helps me not forget about these problems): It's a tree structure, where main is the master node and all other threads are - directly or indirectly - owned by main (main is owned by the OS) OS | main / | \gravity 01 2 || / \ |\ || 3 4 5 6|| / \ \/ 7 8 If any thread lets go of it's parent for any reason, all the children below it fall to their deaths. Hmm...Concurrency Tree Diagrams. Is this already a thing? With some coloured arrows showing message pathways it could be a really nice visualisation of a complex multi-threaded program.
Re: Eponymous template with full template syntax
On 07/01/2013 12:03 PM, Maxim Fomin wrote: > I think that this probably worked as early as in the end of 2011 but I > can be wrong as don't remember exactly. To answer Jonathan's question as well, it must have worked because I see it in code that is definitely tested when it was written. > It seems that dmd recognizes isSmall!int.isSmall as potential UFCS > property, converts isSmall!int to bool and tries to issue call > isSmall(bool) and fails, because that template does not define any > function. That explains it. :) Let's play with it a little: import std.stdio; template isSmall(T) { enum isSmall = (T.sizeof < 12345); struct S { T m; } } struct S { int[10] i; } void main() { writeln(isSmall!int); writeln(isSmall!int.S.init); writeln(isSmall!int.S); } First of all, apparently a template can include a definition with the same name but I still cannot type isSmall!int.isSmall. I guess the above is still an eponymous template and isSmall!int still means isSmall!int.isSmall. Now guess what the last two lines print. :) isSmall!int.S is *not* the S that is included in the template! Here is the output: true S([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) S([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) The last line is actually an anonymous struct object of type S (the S that is defined at module level). That is confusing. Ali
Re: Eponymous template with full template syntax
On Mon, 01 Jul 2013 14:15:04 -0400, Ali Çehreli wrote: I think main's second line used to work: template isSmall(T) { enum isSmall = (T.sizeof < 12345); } void main() { static assert(isSmall!int); // <-- the usual syntax works static assert(isSmall!int.isSmall); // <-- compilation ERROR } Error: template deneme.isSmall does not match any function template declaration. Candidates are: deneme.isSmall(T) Error: template deneme.isSmall(T) cannot deduce template function from argument types !()(bool) Am I imagining it? I don't have a problem with it. :) Was the change intentional? I think it used to work, and I think the change was intentional. I also "discovered" this not too long ago. -Steve
Re: .Exe file how to embed in resource after start program
On 07/01/2013 12:28 PM, Ali GOREN wrote: > Sorry for my bad english. Please don't say that. :) Thank you very much for writing in English so that we can understand you. I don't have an answer to your question though... :-/ Ali
Re: Slices and arrays problems?
Thanks Ali and Adam for the good explanations I understand now.
.Exe file how to embed in resource after start program
Hi. Sorry for my bad english. I want to embed .exe file in resources my program. Etc. Y.JAR embed => DProgram.Exe after if start DProgram.exe Y.Jar program start. :) I'm very, very sorry. Because very bad my english. Thanks :)
Re: Is this a bug in the concurrency lib or am i using it incorrectly?
If you remove the the try..catch you will notice that OwnerTerminated is thrown, if this is the intended behaviour, I don't know. Probably is, because this would be a pretty obvious bug. Ah right, so i guess the main thread is finishing and throwing the exception to writer before sender has sent anything?
Re: Eponymous template with full template syntax
On Monday, 1 July 2013 at 18:15:06 UTC, Ali Çehreli wrote: I think main's second line used to work: template isSmall(T) { enum isSmall = (T.sizeof < 12345); } void main() { static assert(isSmall!int); // <-- the usual syntax works static assert(isSmall!int.isSmall); // <-- compilation ERROR } Error: template deneme.isSmall does not match any function template declaration. Candidates are: deneme.isSmall(T) Error: template deneme.isSmall(T) cannot deduce template function from argument types !()(bool) Am I imagining it? I don't have a problem with it. :) Was the change intentional? Ali I think that this probably worked as early as in the end of 2011 but I can be wrong as don't remember exactly. It seems that dmd recognizes isSmall!int.isSmall as potential UFCS property, converts isSmall!int to bool and tries to issue call isSmall(bool) and fails, because that template does not define any function.
Re: Eponymous template with full template syntax
On Monday, July 01, 2013 11:15:04 Ali Çehreli wrote: > I think main's second line used to work: > > template isSmall(T) > { > enum isSmall = (T.sizeof < 12345); > } > > void main() > { > static assert(isSmall!int); // <-- the usual syntax works > > static assert(isSmall!int.isSmall); // <-- compilation ERROR > } > > Error: template deneme.isSmall does not match any function template > declaration. Candidates are: > deneme.isSmall(T) > Error: template deneme.isSmall(T) cannot deduce template function from > argument types !()(bool) > > Am I imagining it? I don't have a problem with it. :) Was the change > intentional? I'm not aware of it ever having worked, but given that the whole point of eponymous templates is that they be replaced with the symbol carrying their name and _everything_ else in the template is hidden, I would think that what you're seeing is correct behavior. isSmall!int is replaced with the isSmall within isSmall!int, and isSmall.isSmall makes no sense, so if that was allowed before, I'd definitely argue that disallowing it was a bug fix. - Jonathan m Davis
Re: Is this a bug in the concurrency lib or am i using it incorrectly?
> try > { > while (true) > { > receive((string s){ > writefln(s); > }); > } > } > catch (OwnerTerminated ex) > { > // die. > } If you remove the the try..catch you will notice that OwnerTerminated is thrown, if this is the intended behaviour, I don't know. Probably is, because this would be a pretty obvious bug.
Is this a bug in the concurrency lib or am i using it incorrectly?
I was hoping the below example would display 'hello world' but it only displays 'hello'. Is this a bug in the concurrency lib or am i using it incorrectly? import std.stdio; import std.concurrency; void writer() { try { while (true) { receive((string s){ writefln(s); }); } } catch (OwnerTerminated ex) { // die. } } void sender(Tid writer) { send(writer, "world"); } void main(string[] args) { auto writer = spawn(&writer); send(writer, "hello"); spawn(&sender, writer); }
Eponymous template with full template syntax
I think main's second line used to work: template isSmall(T) { enum isSmall = (T.sizeof < 12345); } void main() { static assert(isSmall!int); // <-- the usual syntax works static assert(isSmall!int.isSmall); // <-- compilation ERROR } Error: template deneme.isSmall does not match any function template declaration. Candidates are: deneme.isSmall(T) Error: template deneme.isSmall(T) cannot deduce template function from argument types !()(bool) Am I imagining it? I don't have a problem with it. :) Was the change intentional? Ali
Re: Slices and arrays problems?
On Monday, 1 July 2013 at 17:34:39 UTC, Damian wrote: Isn't the buffer just an array with a fixed length? No. A static array is just a block of memory (like in C), whereas a slice is a struct with a length and pointer to a memory block. A ref slice would write to the length/pointer, which doesn't exist with a static array. You can get a slice from a static array by putting [] on the end, but to be ref, you'll need a variable with the type "int[]" because then the length and pointers can be changed by the function that accepts it.
Re: C standard libraries
On Monday, July 01, 2013 18:32:30 CJS wrote: > Is there some header/module that includes declaration for all C > standard libraries? > > I'm wondering both in general for future reference, and for the > specific case of wanting to time a function and not knowing what > in D--even after looking through the docs--would do something > equivalent to clock and CLOCKS_PER_SEC in the C standard library > time.h. If you want to time a function, checkout std.datetime.StopWatch: http://dlang.org/phobos/std_datetime.html#StopWatch As for C standard library functions in general, as Adam pointed out, they're in the in the core.stdc.* modules. - Jonathan M Davis
Re: Slices and arrays problems?
On 07/01/2013 10:34 AM, Damian wrote: > void testref(ref int[] arr) > { > arr[0] = 1; > } > > void test(int[] arr) > { > arr[0] = 1; > } > > void main() > { > //int[] buffer1 = new int[4]; // This works > int[4] buffer1; // This doesn't > int[4] buffer2; > > testref(buffer1); When that call is made, a slice would have to be created to represent all of the elements of the fixed-length array buffer1. A slice would be needed because buffer1 is not a slice but testref() takes a slice. By the simplest definition, that slice is an rvalue because it is not defined as a variable in the program. And rvalues cannot be bound to non-const references. (If I am not mistaken not even to const references yet, if ever.) > test(buffer2); Similarly, when that call is made, a slice is created. The difference is, because the parameter is by-value, the slice gets copied to test(). Now there is no problem because 'arr' is just a local variable of test(). (Note that when I say a slice is created or a slice is copied, they are very cheap operations. A slice is nothing but the number of elements and a pointer to the first one of those elements. Just a size_t and a pointer.) > > assert(buffer1[0] == 1); > assert(buffer2[0] == 1); > } > > I'm not sure why my code doesn't work?? Isn't the buffer just an array > with a fixed length? DMD is telling me 'buffer1 is not an lvalue'. The > non ref version works fine?! Ali
Slices and arrays problems?
void testref(ref int[] arr) { arr[0] = 1; } void test(int[] arr) { arr[0] = 1; } void main() { //int[] buffer1 = new int[4]; // This works int[4] buffer1; // This doesn't int[4] buffer2; testref(buffer1); test(buffer2); assert(buffer1[0] == 1); assert(buffer2[0] == 1); } I'm not sure why my code doesn't work?? Isn't the buffer just an array with a fixed length? DMD is telling me 'buffer1 is not an lvalue'. The non ref version works fine?!
Re: C standard libraries
On Monday, 1 July 2013 at 16:32:32 UTC, CJS wrote: Is there some header/module that includes declaration for all C standard libraries? It is in core.stdc. For example: import core.stdc.stdio; // import core.stdc.stdlib;// etc. what in D--even after looking through the docs--would do something equivalent to clock and CLOCKS_PER_SEC in the C standard library time.h. import core.stdc.time; import std.stdio; // for writeln writeln(CLOCKS_PER_SEC); The C headers in D aren't much documented, but they have all the same stuff as in C itself, so if you translate the include to import, the rest should continue to just work. If you want to get to more OS specific stuff, outside the C standard but still typical C libs, it is core.sys.posix.unistd; /* */ core.sys.windows.windows /* */ and so on. The windows.h translation is *horribly* incomplete though, so if you want to do a serious win32 program you'll probably want to get something else. There's a win32 bindings somewhere on the net, if you need it I can find the link.
C standard libraries
Is there some header/module that includes declaration for all C standard libraries? I'm wondering both in general for future reference, and for the specific case of wanting to time a function and not knowing what in D--even after looking through the docs--would do something equivalent to clock and CLOCKS_PER_SEC in the C standard library time.h.
Re: GC dead-locking ?
Am Tue, 18 Jun 2013 19:12:06 -0700 schrieb Sean Kelly : > On Jun 18, 2013, at 7:01 AM, Marco Leise wrote: > > > Am Mon, 17 Jun 2013 10:46:19 -0700 > > schrieb Sean Kelly : > > > >> On Jun 13, 2013, at 2:22 AM, Marco Leise wrote: > >> > >>> Here is an excerpt from a stack trace I got while profiling > >>> with OProfile: > >>> > >>> #0 sem_wait () from /lib64/libpthread.so.0 > >>> #1 thread_suspendAll () at core/thread.d:2471 > >>> #2 gc.gcx.Gcx.fullcollect() (this=...) at gc/gcx.d:2427 > >>> #3 gc.gcx.Gcx.bigAlloc() (this=..., size=16401, poolPtr=0x7fc3d4bfe3c8, > >>> alloc_size=0x7fc3d4bfe418) at gc/gcx.d:2099 > >>> #4 gc.gcx.GC.mallocNoSync (alloc_size=0x7fc3d4bfe418, bits=10, > >>> size=16401, this=...) gc/gcx.d:503 > >>> #5 gc.gcx.GC.malloc() (this=..., size=16401, bits=10, > >>> alloc_size=0x7fc3d4bfe418) gc/gcx.d:421 > >>> #6 gc.gc.gc_qalloc (ba=10, sz=) gc/gc.d:203 > >>> #7 gc_qalloc (sz=, ba=10) gc/gc.d:198 > >>> #8 _d_newarrayT (ti=..., length=4096) rt/lifetime.d:807 > >>> #9 sequencer.algorithm.gzip.HuffmanTree.__T6__ctorTG32hZ.__ctor() > >>> (this=..., bitLengths=...) sequencer/algorithm/gzip.d:444 > >>> > >>> Two more threads are alive, but waiting on a condition > >>> variable (i.e.: in pthread_cond_wait(), but from my own and > >>> not from druntime code. Is there some obvious way I could have > >>> dead-locked the GC ? Or is there a bug ? > >> > >> I assume you're running on Linux, which uses signals (SIGUSR1, > >> specifically) to suspend threads for a collection. So I imagine what's > >> happening is that your thread is trying to suspend all the other threads > >> so it can collect, and those threads are ignoring the signal for some > >> reason. I would expect pthread_cond_wait to be interrupted if a signal > >> arrives though. Have you overridden the signal handler for SIGUSR1? > > > > No, I have not overridden the signal handler. I'm aware of the > > fact that signals make pthread_cond_wait() return early and > > put them in a while loop as one would expect, that is all. > > Hrm... Can you trap this in a debugger and post the stack traces of all > threads? That stack above is a thread waiting for others to say they're > suspended so it can collect. I could do that (with a little work setting the scenario up again), but it wont help. As I said, the other two threads were paused in pthread_cond_wait() in my own code. There was nothing special about their stack trace. -- Marco
Re: Handling different types gracefully
On Monday, 1 July 2013 at 12:03:25 UTC, Roderick Gibson wrote: I'm asking because I'm doing some game development in D and I've come upon the entity component architecture, and it looks like a good way to handle the complexity and interdependency that games seem to have. The components wind up being plain old data types (I currently use structs), with systems that actually modify and interact with them on a per-entity basis. The basic idea is that you compose entities (basically just an id) with various components to give the specific functionality you need for that particular game object. The whole entity system is just a database for the different subsystems to query for entities (just an id) which have components that fulfill their criteria (for example a physics subsystem might only be interested in entities with the components position, movement, and collision, while a render subsystem might only be interested in entities with components position, mesh, sprite). There's also the reverse where the subsystems register which components they are looking for and then the entity system serves up entities that match the criteria. The standard way to store components is just to subclass them from a base class "Component" and then store a pointer to them in a Component[] in an overall entity manager. But then you have to do things like type casting the pointers when you return the queries, which seems a bit rough. It also feels wrong to make them inherit a class for the SOLE reason of getting around the type system. Anyway, I think I'm just rubber ducking a bit here, but I'm wondering if there's another way to do this, if someone has any experience with this sort of system. As an example of what I'm looking for, say there is a class Entities, with some type of container that could hold arrays of different component types (this is the part that really stumps me). I'd like to be able to do something like: ... auto entities = new Entities(); auto entity_id = entities.createEntity(); entities.addComponent!(position)(entity_id, pos); entities.addComponent!(movement)(entity_id, mov); entities.addComponent!(collision)(entity_id, col); auto physics_data = entities.getEntitiesWithComponents!(position, movement, collision)(); The two big requirements are some kind of regular, queryable structure to hold the components (of different types), and the ability to filter by type. Is anything like that remotely possible? Waiting for multiple "alias this" ?? And opDispatch to respond to unimplemented components.
Re: Handling different types gracefully
Roderick Gibson: auto entities = new Entities(); auto entity_id = entities.createEntity(); entities.addComponent!(position)(entity_id, pos); entities.addComponent!(movement)(entity_id, mov); entities.addComponent!(collision)(entity_id, col); auto physics_data = entities.getEntitiesWithComponents!(position, movement, collision)(); The two big requirements are some kind of regular, queryable structure to hold the components (of different types), and the ability to filter by type. Is anything like that remotely possible? If the possible types are know, then there's std.variant.Algebraic, otherwise there is a free Variant or VariantN. They are not perfect, but maybe they are good enough for you. Bye, bearophile
Handling different types gracefully
I'm asking because I'm doing some game development in D and I've come upon the entity component architecture, and it looks like a good way to handle the complexity and interdependency that games seem to have. The components wind up being plain old data types (I currently use structs), with systems that actually modify and interact with them on a per-entity basis. The basic idea is that you compose entities (basically just an id) with various components to give the specific functionality you need for that particular game object. The whole entity system is just a database for the different subsystems to query for entities (just an id) which have components that fulfill their criteria (for example a physics subsystem might only be interested in entities with the components position, movement, and collision, while a render subsystem might only be interested in entities with components position, mesh, sprite). There's also the reverse where the subsystems register which components they are looking for and then the entity system serves up entities that match the criteria. The standard way to store components is just to subclass them from a base class "Component" and then store a pointer to them in a Component[] in an overall entity manager. But then you have to do things like type casting the pointers when you return the queries, which seems a bit rough. It also feels wrong to make them inherit a class for the SOLE reason of getting around the type system. Anyway, I think I'm just rubber ducking a bit here, but I'm wondering if there's another way to do this, if someone has any experience with this sort of system. As an example of what I'm looking for, say there is a class Entities, with some type of container that could hold arrays of different component types (this is the part that really stumps me). I'd like to be able to do something like: ... auto entities = new Entities(); auto entity_id = entities.createEntity(); entities.addComponent!(position)(entity_id, pos); entities.addComponent!(movement)(entity_id, mov); entities.addComponent!(collision)(entity_id, col); auto physics_data = entities.getEntitiesWithComponents!(position, movement, collision)(); The two big requirements are some kind of regular, queryable structure to hold the components (of different types), and the ability to filter by type. Is anything like that remotely possible?
Assert failures in threads
I've noticed that when an assert fails inside a thread, no error message is printed and the program/thread just hangs. Is there any way to ensure that an assertion failure inside a thread does output a message? For the purposes of my current needs, it's fine if it also brings down the whole program, just so long as I'm alerted to what generated the error.