Re: What is difference between struct and class?
On Monday, 3 June 2019 at 00:47:27 UTC, Adam D. Ruppe wrote: On Monday, 3 June 2019 at 00:17:08 UTC, Rnd wrote: What additional features do classes offer in D? Classes support built-in runtime polymorphism through inheritance. structs don't. As a result of this, classes are a little bit heavier resource-wise and are semantically always object references. I am not clear if structs can have constructors (this) and whether they can be multiple? Also can data be made private and getters and setters used to access them?
Re: What is difference between struct and class?
On Monday, 3 June 2019 at 00:17:08 UTC, Rnd wrote: What additional features do classes offer in D? Classes support built-in runtime polymorphism through inheritance. structs don't. As a result of this, classes are a little bit heavier resource-wise and are semantically always object references.
What is difference between struct and class?
I see that struct can have data as well as member functions and instances can be created. So they sound like classes only. What additional features do classes offer in D?
Re: import and call
On Sunday, 2 June 2019 at 19:38:11 UTC, Amex wrote: I thought importing single functions were suppose to be faster. Am I wrong? That is wrong. Importing is always done of the whole module. All the `: func` thing does is limit the things introduced to the namespace.
Re: Very simple null reference escape
On Sunday, 2 June 2019 at 07:55:27 UTC, Amex wrote: A.B If A is null, crash. A?.B : writeln("HAHA"); No crash, ignored, equivalent to if (A is null) writeln("HAHA"); else A.B; safeAccess from iz does this : https://github.com/Basile-z/iz/blob/master/import/iz/sugar.d#L1666
Re: import and call
On Sunday, 2 June 2019 at 19:38:11 UTC, Amex wrote: Tired of having to import a single function to call it. Since mod.foo(x); doesn't work since mod is not defined. we have to do import mod : foo; foo(x); Why not mod:foo(x)? or mod#foo(x) or mod@foo(x) or whatever Reduces 50% of the lines and reduces the import symbol. I realize that we could do import m = mod; m.foo(x); but the idea is to only import the single function. I'm not sure if it matters. I thought importing single functions were suppose to be faster. Am I wrong? The idea is to reduce having to litter the code with imports which I find I'm always having to do, or to make them global... just for a few calls in to them. Expression based import is possible using mixin, see https://dlang.org/blog/2017/02/13/a-new-import-idiom/
Re: 'version'-based code selection
On Sunday, June 2, 2019 11:43:09 AM MDT Anonymouse via Digitalmars-d-learn wrote: > On Saturday, 1 June 2019 at 07:46:40 UTC, Jonathan M Davis wrote: > > For the most part though, you don't declare your own version > > identifiers. It sometimes makes sense, but usually, version > > identifiers are used for versioning code based on the platform > > or architecture that it's compiled on. They're really only > > intended to be a saner version of #ifdefs, and if you're doing > > anything fancy with them, you're really not using them as > > intended and are probably going to have problems. > > I use versioning pervasively to make features opt-in/opt-out at > compile-time. > > Like so, from dub.json: > > "versions": > [ > "AsAnApplication", > "WithAdminPlugin", > "WithAutomodePlugin", > "WithBashQuotesPlugin", > "WithChanQueriesService", > "WithChatbotPlugin", > "WithConnectService", > "WithCTCPService", > "WithHelpPlugin", > "WithNotesPlugin", > "WithPersistenceService", > "WithPipelinePlugin", > "WithPrinterPlugin", > "WithQuotesPlugin", > "WithSedReplacePlugin", > "WithSeenPlugin", > "WithWebtitlesPlugin" > ], > > --- > > module foo; > > version(WithFoo): > > // ... > > Is this recommended against? It's a very convenient way of > enabling and disabling modules outright, since (by default) dub > eagerly compiles everything it sees. I haven't had any problems > with it as of yet, at the very least. Personally, I wouldn't be in favor of doing much in the way of enabling or disabling features in a library or application in such a manner, but if you're going to do it, then version identifiers would be appropriate. However, you do need to watch out, because such an approach runs the risk of problems if you end up with a project depending on libraries that depend on your library, because they may not be compiled with the same set of version identifiers. I'm not sure how dub handles that (probably by considering it a conflict), but without any form of conflict resolution (or you have a form of conflict resolution that doesn't catch this issue), you run the risk of modules being imported with one set of version identifiers but actually compiled with another. In some situations, that will result in a linker error, but in others, it's just going to result in the code not behaving as expected. It's less of an issue if the version identifiers are for an application rather than a library. Also, if you're versioning out entire modules rather than pieces of modules, you're likely to be less at risk of subtle problems, since then you'll just get large stuff missing, and linking will fail, whereas if you're using such version identifiers within code (e.g. changing the body of a function), then you run a high risk of subtle problems. Personally, if I were writing a library with optional stuff, I'd make the optional stuff into sub-modules and try to avoid using version identifiers. I might do it for an application though, since in that case, you wouldn't be dealing with sub-modules, and you're not dealing with anything depending on your code, just controlling what ends up in the executable. - Jonathan M Davis
Re: Very simple null reference escape
On Sunday, 2 June 2019 at 14:37:48 UTC, Paul Backus wrote: On Sunday, 2 June 2019 at 07:55:27 UTC, Amex wrote: A.B If A is null, crash. A?.B : writeln("HAHA"); No crash, ignored, equivalent to if (A is null) writeln("HAHA"); else A.B; The "optional" package on dub [1] has a .dispatch method that does this: auto d = some(A()); // Dispatch to one of its methods d.dispatch.f(); // calls a.f, returns some(4) d.dispatch.inner.g(); // calls a.inner.g, returns some(7) // Use on a pointer or reference type as well A* e = null; // If there's no value in the reference type, dispatching // works, and produces an optional assert(e.dispatch.f() == none); assert(e.dispatch.inner.g() == none); Full example: https://run.dlang.io/is/SmsGQu [1] https://code.dlang.org/packages/optional thanks.
Error: module `M.Q` from file M\Q.d conflicts with another module Q from file M\Q.d
main.d(217): Error: module `M.Q` from file M\Q.d conflicts with another module Q from file M\Q.d the line is simply import Q : foo; the problem is that it should have been import M.Q : foo; There is no module Q. The error message is in error! There is no other module. the module is named module M.Q; where M is a subdirectory. This is probably suppose to be module Q; but everything works out. The error message could be more accurate(took me a min to figure out what was going on).
import and call
Tired of having to import a single function to call it. Since mod.foo(x); doesn't work since mod is not defined. we have to do import mod : foo; foo(x); Why not mod:foo(x)? or mod#foo(x) or mod@foo(x) or whatever Reduces 50% of the lines and reduces the import symbol. I realize that we could do import m = mod; m.foo(x); but the idea is to only import the single function. I'm not sure if it matters. I thought importing single functions were suppose to be faster. Am I wrong? The idea is to reduce having to litter the code with imports which I find I'm always having to do, or to make them global... just for a few calls in to them.
Re: hasElaborateCopyConstructor bug?
On Sunday, June 2, 2019 1:29:22 PM MDT Jonathan M Davis via Digitalmars-d- learn wrote: > On Sunday, June 2, 2019 8:32:16 AM MDT Paul Backus via Digitalmars-d-learn > wrote: > > On Sunday, 2 June 2019 at 06:59:02 UTC, Jonathan M Davis wrote: > > > Almost certainly, hasElaborateCopyConstructor should be updated > > > to test for both postblit constructors and copy constructors, > > > since its purpose is to test for whether the type has a > > > user-defined copying function [...] Whether > > > hasElaborateCopyConstructor was the best name is debatable, but > > > it _does_ involve "elaborate" copying, and copy constructors > > > weren't actually in the language at the time. The documentation > > > is wonderfully confusing though in that it talks about copy > > > constructors and then says that a copy constructor is > > > introduced by defining this(this) for a struct. So, it > > > basically calls a postblit constructor a copy constructor. > > > > I've made the mistake in the past of trying to use > > hasElaborateCopyConstructor to test for the presence of > > __xpostblit, and I'm sure I'm not the only one. The name is quite > > misleading--even more so now that D has real copy constructors. > > > > If std.v2 ever materializes, we'll have an opportunity to fix > > papercuts like this. Until then, my preferred workaround is to > > use a renaming import: > > > > import std.traits: hasNontrivialCopy = > > hasElaborateCopyConstructor; > > Why is it a mistake to use hasElaborateCopyConstructor to test for > __xpostblit? Because you're trying to test for __xpostblit for some > purpose other than determining whether the type is blittable? I'm not > sure what other reason there would be to test for __xpostblit though. > Either way, hasElaborateCopyConstructor currently checks for exactly that > (with the addition that it checks whether a static array has elements > with __xpostblit): > > template hasElaborateCopyConstructor(S) > { > static if (__traits(isStaticArray, S) && S.length) > { > enum bool hasElaborateCopyConstructor = > hasElaborateCopyConstructor! (typeof(S.init[0])); > } > else static if (is(S == struct)) > { > enum hasElaborateCopyConstructor = __traits(hasMember, S, > "__xpostblit"); > } > else > { > enum bool hasElaborateCopyConstructor = false; > } > } > > My point was that given the purpose of hasElaborateCopyConstructor, > updating it to test for both a postblit constructor and copy constructor > would be appropriate. In fact, the fact that it hasn't been means that > the introduction of copy constructors has broken existing code (or at > least that such code won't interact correctly with structs that have copy > constructors). There should be no need to rename the trait, just update > it, and whether it uses the name "elaborate" or "non-trivial" is pretty > much irrelevant. Personally, I probably would have chosen hasNonTrivial > over hasElaborate, but they mean the same thing, and we have > hasElaborateDestructor for the corresponding test for destructors and > hasElaborateAssign for the corresponding test for assignment. It really > doesn't make sense to change the name at this point. It looks like Manu already reported a bug on this: https://issues.dlang.org/show_bug.cgi?id=19902 - Jonathan M Davis
Re: hasElaborateCopyConstructor bug?
On Sunday, June 2, 2019 8:32:16 AM MDT Paul Backus via Digitalmars-d-learn wrote: > On Sunday, 2 June 2019 at 06:59:02 UTC, Jonathan M Davis wrote: > > Almost certainly, hasElaborateCopyConstructor should be updated > > to test for both postblit constructors and copy constructors, > > since its purpose is to test for whether the type has a > > user-defined copying function [...] Whether > > hasElaborateCopyConstructor was the best name is debatable, but > > it _does_ involve "elaborate" copying, and copy constructors > > weren't actually in the language at the time. The documentation > > is wonderfully confusing though in that it talks about copy > > constructors and then says that a copy constructor is > > introduced by defining this(this) for a struct. So, it > > basically calls a postblit constructor a copy constructor. > > I've made the mistake in the past of trying to use > hasElaborateCopyConstructor to test for the presence of > __xpostblit, and I'm sure I'm not the only one. The name is quite > misleading--even more so now that D has real copy constructors. > > If std.v2 ever materializes, we'll have an opportunity to fix > papercuts like this. Until then, my preferred workaround is to > use a renaming import: > > import std.traits: hasNontrivialCopy = > hasElaborateCopyConstructor; Why is it a mistake to use hasElaborateCopyConstructor to test for __xpostblit? Because you're trying to test for __xpostblit for some purpose other than determining whether the type is blittable? I'm not sure what other reason there would be to test for __xpostblit though. Either way, hasElaborateCopyConstructor currently checks for exactly that (with the addition that it checks whether a static array has elements with __xpostblit): template hasElaborateCopyConstructor(S) { static if (__traits(isStaticArray, S) && S.length) { enum bool hasElaborateCopyConstructor = hasElaborateCopyConstructor! (typeof(S.init[0])); } else static if (is(S == struct)) { enum hasElaborateCopyConstructor = __traits(hasMember, S, "__xpostblit"); } else { enum bool hasElaborateCopyConstructor = false; } } My point was that given the purpose of hasElaborateCopyConstructor, updating it to test for both a postblit constructor and copy constructor would be appropriate. In fact, the fact that it hasn't been means that the introduction of copy constructors has broken existing code (or at least that such code won't interact correctly with structs that have copy constructors). There should be no need to rename the trait, just update it, and whether it uses the name "elaborate" or "non-trivial" is pretty much irrelevant. Personally, I probably would have chosen hasNonTrivial over hasElaborate, but they mean the same thing, and we have hasElaborateDestructor for the corresponding test for destructors and hasElaborateAssign for the corresponding test for assignment. It really doesn't make sense to change the name at this point. - Jonathan M Davis
Re: What does ! Stand for in map! and filter! function calls?
On Sunday, 2 June 2019 at 16:39:57 UTC, Rnd wrote: Is it not possible in the language to have template map function also to called as map(x=>... ? That would be slower, and std.algorithm generally disallows easy but slow functions. In Java, you can sort a linked list. In D, sort requires an array (or random access range). D's `uniq` removes duplicates, but assumes the input range is sorted. Of course you can do myLinkedList.array.sort.uniq but it's not as easy as myLinkedList.uniq because that hides all the stuff that is required to happen behind the scenes. It may be less beginner friendly, but I've also seen newcomers come with a question among the lines of 'I'm trying out the language, why is my little benchmark slower than equivalent Javascript' after which they're told 'don't use dmd, don't use 80-bit floats, use these compiler flags' etc. So it's a trade-off between ease of use by default and performance by default. A clear error message on `map` without ! is the way to go in my opinion.
Re: 'version'-based code selection
On Saturday, 1 June 2019 at 07:46:40 UTC, Jonathan M Davis wrote: For the most part though, you don't declare your own version identifiers. It sometimes makes sense, but usually, version identifiers are used for versioning code based on the platform or architecture that it's compiled on. They're really only intended to be a saner version of #ifdefs, and if you're doing anything fancy with them, you're really not using them as intended and are probably going to have problems. I use versioning pervasively to make features opt-in/opt-out at compile-time. Like so, from dub.json: "versions": [ "AsAnApplication", "WithAdminPlugin", "WithAutomodePlugin", "WithBashQuotesPlugin", "WithChanQueriesService", "WithChatbotPlugin", "WithConnectService", "WithCTCPService", "WithHelpPlugin", "WithNotesPlugin", "WithPersistenceService", "WithPipelinePlugin", "WithPrinterPlugin", "WithQuotesPlugin", "WithSedReplacePlugin", "WithSeenPlugin", "WithWebtitlesPlugin" ], --- module foo; version(WithFoo): // ... Is this recommended against? It's a very convenient way of enabling and disabling modules outright, since (by default) dub eagerly compiles everything it sees. I haven't had any problems with it as of yet, at the very least.
Re: What does ! Stand for in map! and filter! function calls?
On Sunday, 2 June 2019 at 16:39:57 UTC, Rnd wrote: Is it not possible in the language to have template map function also to called as map(x=>... ? This will reduce complexity which will attract more people to this language. Easy languages have great mass appeal as has been shown with Ruby and Python. It's possible, but I believe the version that takes the function as a template argument is easier for the compiler to optimize, so doing it that way is a better choice for the standard library. Reducing complexity for first-time learners is a noble goal, but templates are used so pervasively in D that there's really no sense in trying to avoid them. If you'd like to learn more about D's templates, Philippe Sigaud has written an excellent tutorial: https://github.com/PhilippeSigaud/D-templates-tutorial/blob/master/D-templates-tutorial.md
Re: What does ! Stand for in map! and filter! function calls?
On Sunday, 2 June 2019 at 16:39:57 UTC, Rnd wrote: Is it not possible in the language to have template map function also to called as map(x=>... ? It could be done pretty easily, but you will have to learn what template arguments are eventually anyway. You'll see this pattern all over, like `to!string(...)` among others that come up pretty early using D.
Re: What does ! Stand for in map! and filter! function calls?
On Sunday, 2 June 2019 at 15:55:46 UTC, Paul Backus wrote: On Sunday, 2 June 2019 at 15:48:54 UTC, Rnd wrote: I have recently started using Dlang, hence this basic question. Thanks for your insight. map and filter are templates in D, and !(...) is D's syntax for passing arguments to templates: map!(x => x*x)([1, 2, 3, 4, 5]) ^ ^ | | | +- This array is a normal function argument | +- This lambda is a template argument Is it not possible in the language to have template map function also to called as map(x=>... ? This will reduce complexity which will attract more people to this language. Easy languages have great mass appeal as has been shown with Ruby and Python.
Re: What does ! Stand for in map! and filter! function calls?
On Sunday, 2 June 2019 at 15:48:54 UTC, Rnd wrote: I have recently started using Dlang, hence this basic question. Thanks for your insight. To know more about D you should take the time to do the D tour [1] which provides you with general knowledge of most of D's functionalities and vocabulary. To know more about templates specifically, check out this tutorial [2]. [1]: https://tour.dlang.org/ [2]: http://nomad.uk.net/articles/templates-in-d-explained.html
Re: What does ! Stand for in map! and filter! function calls?
On Sunday, 2 June 2019 at 15:48:54 UTC, Rnd wrote: I have recently started using Dlang, hence this basic question. Thanks for your insight. map and filter are templates in D, and !(...) is D's syntax for passing arguments to templates: map!(x => x*x)([1, 2, 3, 4, 5]) ^ ^ | | | +- This array is a normal function argument | +- This lambda is a template argument
What does ! Stand for in map! and filter! function calls?
I have recently started using Dlang, hence this basic question. Thanks for your insight.
Re: hasElaborateCopyConstructor bug?
On Sunday, 2 June 2019 at 14:44:47 UTC, H. S. Teoh wrote: On Sun, Jun 02, 2019 at 02:32:16PM +, Paul Backus via Digitalmars-d-learn wrote: [...] If std.v2 ever materializes, we'll have an opportunity to fix papercuts like this. Until then, my preferred workaround is to use a renaming import: import std.traits: hasNontrivialCopy = hasElaborateCopyConstructor; Couldn't we just rename hasElaborateCopyConstructor to hasNontrivialCopy and leave a deprecated alias from the former to the latter? (Or perhaps without the deprecation, but the documentation would use the new name and hopefully new code would, too.) T My impression was that a pure name change would be unlikely to pass review (see for example https://github.com/dlang/phobos/pull/6227). But perhaps it's worth submitting the PR anyway just to see what happens.
Re: hasElaborateCopyConstructor bug?
On Sun, Jun 02, 2019 at 02:32:16PM +, Paul Backus via Digitalmars-d-learn wrote: [...] > If std.v2 ever materializes, we'll have an opportunity to fix > papercuts like this. Until then, my preferred workaround is to use a > renaming import: > > import std.traits: hasNontrivialCopy = hasElaborateCopyConstructor; Couldn't we just rename hasElaborateCopyConstructor to hasNontrivialCopy and leave a deprecated alias from the former to the latter? (Or perhaps without the deprecation, but the documentation would use the new name and hopefully new code would, too.) T -- Unix was not designed to stop people from doing stupid things, because that would also stop them from doing clever things. -- Doug Gwyn
Re: Very simple null reference escape
On Sunday, 2 June 2019 at 07:55:27 UTC, Amex wrote: A.B If A is null, crash. A?.B : writeln("HAHA"); No crash, ignored, equivalent to if (A is null) writeln("HAHA"); else A.B; The "optional" package on dub [1] has a .dispatch method that does this: auto d = some(A()); // Dispatch to one of its methods d.dispatch.f(); // calls a.f, returns some(4) d.dispatch.inner.g(); // calls a.inner.g, returns some(7) // Use on a pointer or reference type as well A* e = null; // If there's no value in the reference type, dispatching // works, and produces an optional assert(e.dispatch.f() == none); assert(e.dispatch.inner.g() == none); Full example: https://run.dlang.io/is/SmsGQu [1] https://code.dlang.org/packages/optional
Re: hasElaborateCopyConstructor bug?
On Sunday, 2 June 2019 at 06:59:02 UTC, Jonathan M Davis wrote: Almost certainly, hasElaborateCopyConstructor should be updated to test for both postblit constructors and copy constructors, since its purpose is to test for whether the type has a user-defined copying function [...] Whether hasElaborateCopyConstructor was the best name is debatable, but it _does_ involve "elaborate" copying, and copy constructors weren't actually in the language at the time. The documentation is wonderfully confusing though in that it talks about copy constructors and then says that a copy constructor is introduced by defining this(this) for a struct. So, it basically calls a postblit constructor a copy constructor. I've made the mistake in the past of trying to use hasElaborateCopyConstructor to test for the presence of __xpostblit, and I'm sure I'm not the only one. The name is quite misleading--even more so now that D has real copy constructors. If std.v2 ever materializes, we'll have an opportunity to fix papercuts like this. Until then, my preferred workaround is to use a renaming import: import std.traits: hasNontrivialCopy = hasElaborateCopyConstructor;
Re: Reading .pem files for secured
On Friday, 31 May 2019 at 12:17:14 UTC, Sebastiaan Koppe wrote: Just base64 decode the PEM data (without the ) and feed it to RSA.this(ubyte[] publicKey). Ought to be that simple. I assume the same should apply with private key and private key constructor (along with a random password of course)?
Re: Reading .pem files for secured
On Friday, 31 May 2019 at 12:17:14 UTC, Sebastiaan Koppe wrote: Just base64 decode the PEM data (without the ) and feed it to RSA.this(ubyte[] publicKey). Ought to be that simple. That's logic of SSL? Okay, I'll try that first.
Re: How to create an overwriteable struct that is always const?
Ah, fair enough.
Re: 'version'-based code selection
On Saturday, 1 June 2019 at 07:46:40 UTC, Jonathan M Davis wrote: Like static ifs, version statements are completely a compile-time construct and having nothing to do with runtime beyond how they affect the code that's generated. ... - Jonathan M Davis Thanks for taking the time. That's it then for selecting between malloc/free implementations at runtime (program start-up time, usually) in such a way. There might still be hope in the form of a separate dynamic library with re-implemented malloc, and equivalent wrapper API's around libc in another library (whole program, including Phobos, relying on the same malloc library).
Re: How to create an overwriteable struct that is always const?
On 02.06.19 04:22, David Zhang wrote: 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. The `string` itself can be modified: You can change its length, and you can make it refer to other characters. That's modifying. You can't modify the string's characters, because the string refers to them with an `immutable(char)*` pointer. That means the pointer itself is mutable (can be modified), but the data it points to is immutable (can't be modified). You can do the same in your struct: `const(char)* pointer;`. Then you can modify the pointer but you can't modify the data it points to.
Very simple null reference escape
A.B If A is null, crash. A?.B : writeln("HAHA"); No crash, ignored, equivalent to if (A is null) writeln("HAHA"); else A.B;
Re: hasElaborateCopyConstructor bug?
On Saturday, June 1, 2019 5:29:08 PM MDT SrMordred via Digitalmars-d-learn wrote: > On Saturday, 1 June 2019 at 21:39:33 UTC, SImen Kjærås wrote: > > On Saturday, 1 June 2019 at 21:05:32 UTC, SrMordred wrote: > > > > hasElaborateCopyConstructor checks if the type defines a > > postblit[0]. > > Yes, I know this. > > But since dmd 2.086 we have copy ctors: > https://dlang.org/changelog/2.086.0.html#copy_constructor > > And its seem logical that if I want a trait that check if copy > ctors exists I will use this name 'hasElaborateCopyConstructor' > > So it looks like a naming issue for me. > Unless postblits will be eventually replaced by copy ctors. Effectively, postblit constructors are being replaced by copy constructors. Ideally, no new code would be written with postblit constructors, and all existing postblit constructors would eventually be replaced with copy constructors. However, because of how long postblit constructors have existed in the language, Walter has no interest in actually deprecating them until he actually has to (so potentially never) in order to avoid code breakage. Almost certainly, hasElaborateCopyConstructor should be updated to test for both postblit constructors and copy constructors, since its purpose is to test for whether the type has a user-defined copying function (be it explicitly or because the type contains a type with a user-defined copying function) - and thus whether copying the type involves anything other than simply blitting. Historically, the user-defined copying function has been the postblit constructor, but whether it's a postblit constructor or a copy constructor is pretty much irrelevant to the purpose of the trait. It does make _some_ sense that it's not hasPostblit or hasPostblitConstructor, because that could easily be misconstrued as being whether it explicitly has a user-defined postblit constructor, which isn't what it tests. If a type has a postblit constructor in it directly, it has the member __postblit and the member __xpostblit (where __postblit is the explicitly declared postblit constructor and __xpostblit is what calls the postblit constructor). However, if the type does not directly declare a postblit constructor but it has a member that does declare one (directly or indirectly), then it will just have __xpostblit, which will in turn deal with copying each member correctly. So, calling the trait hasPostblit could easily have given the wrong impression. Whether hasElaborateCopyConstructor was the best name is debatable, but it _does_ involve "elaborate" copying, and copy constructors weren't actually in the language at the time. The documentation is wonderfully confusing though in that it talks about copy constructors and then says that a copy constructor is introduced by defining this(this) for a struct. So, it basically calls a postblit constructor a copy constructor. Regardless, as long as changing hasElaborateCopyConstructor to test for both the postblit constructor and the copy constructor isn't likely to break anything (and I don't _think_ that it will, but I'd have to think about it more to say for sure), then it should just be updated to take copy constructors into account. And if we ever do reach the point that we actually fully get rid of postblit constructors, then hasElaborateCopyConstructor can be updated to not test for postblit constructors any longer. - Jonathan M Davis
Re: How to create an overwriteable struct that is always const?
On Saturday, June 1, 2019 8:23:58 PM MDT David Zhang via Digitalmars-d-learn wrote: > 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. If the member functions are const or inout, then they won't be able to modify any members. - Jonathan M Davis