- "C++ Modules Might Be Dead-on-Arrival" - 15 Updates
- "Is C++ fast?" - 3 Updates
- My C++ blog - 3 Updates
Bart <bc@freeuk.com>: Jan 30 11:37PM On 30/01/2019 22:18, Melzzzzz wrote: >> void f(){g("two"); g(&f);} >> void g(float x){}; > No. You don't have type check. I meant no need for prototypes. Which you get with out of order declarations. I solved this long ago in my own languages, and wouldn't be able to do without the feature now. However, while it was easy to solve within one module (it just needs an extra pass compared with C or C++), dealing with mutually imported modules is another matter. >> has modules: > This problem is solved in other languages. You either parse all library > files as single file, or .... My approach [in my language] works when all source files comprising the program unit (single executable or library file) are compiled at the same time, sharing a global symbol table (the output is the executable). Parsing is performed across all modules before proceeding to the next stage, which is resolving names. And that process can now cross between modules because everything is in memory. (For external libraries it still relies on manually created files of declarations, necessary anyway as most will be in a different language.) There are still a number of problems, one of which is this: with a purely hierarchical import structure, it is easy to construct a load-order for the modules. That means that when modules contain initialisation routines, all those can automatically be called in the right order. But with circular imports, that load-order is not determinable. If A imports B, and B imports A, whose initialisation routine do you call first? Each may require the other to have been set up already. You have to sort it out manually. -- bart |
Melzzzzz <Melzzzzz@zzzzz.com>: Jan 30 10:19PM > "make" (or ninja, or whatever) will handle it fine. If you have enough > modules for the build speed and parallel compilation to matter, there > will be plenty of opportunity for parallelising. No problems with make. Compilers must accomodate. -- press any key to continue or any other to quit... |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 31 08:14AM +0200 On 31.01.2019 1:37, Bart wrote: > my own languages, and wouldn't be able to do without the feature now. > However, while it was easy to solve within one module (it just needs an > extra pass compared with C or C++) C++ is perfectly capable of doing the needed extra pass by itself, it just needs a little syntax sugar: struct mynamespace { static void f(double x) { g(x-1); } static void g(float x) { if (x>0) { f(x); }} }; int main() { mynamespace::f(100); } |
David Brown <david.brown@hesbynett.no>: Jan 31 08:23AM +0100 On 31/01/2019 00:37, Bart wrote: >> No. You don't have type check. I meant no need for prototypes. > Which you get with out of order declarations. I solved this long ago in > my own languages, and wouldn't be able to do without the feature now. C, C++ and many other languages support declarations (or "prototypes", or "forward declarations" - the terminology varies by language) before definitions. That solves any circular dependency issues within a module quite happily. Co-recursive functions are a rarity in code. Some people like to organise their files "backwards" - they like to define a function first, then further down in the file they define the functions that it calls. That is fine, but will mean you need more separate prototype declarations in C. For people who like that code arrangement, C's methods are a little inconvenient. (As Paavo points out, C++ no longer needs that if you feel it is an issue.) > However, while it was easy to solve within one module (it just needs an > extra pass compared with C or C++), dealing with mutually imported > modules is another matter. Ordering is not a problem in the slightest for modules. Mutually dependent imports (circular imports) are an issue, but these can almost always be avoided in your code structuring. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jan 31 06:47AM -0500 On 1/31/19 02:23, David Brown wrote: ... > C, C++ and many other languages support declarations (or "prototypes", > or "forward declarations" - the terminology varies by language) before > definitions. While the terminology does vary by language, neither C nor C++ use the term "prototype" to make such a distinction. Do you know of some other language where it is used for that purpose? In C and C++, a prototype can occur in either a forward declaration or in the declaration that appears at the start of a function definition. In C, a forward declaration need not be a prototype, and the same is true of the declaration which appears a the start of a function definition. "forward declaration" and "defining declaration" is a distinction that's completely independent of the distinction between "prototyped declaration" and "non-prototyped declaration" (with the latter appearing only in C). |
Bart <bc@freeuk.com>: Jan 31 12:06PM On 31/01/2019 07:23, David Brown wrote: > or "forward declarations" - the terminology varies by language) before > definitions. That solves any circular dependency issues within a module > quite happily. That doesn't solve it at all. Actually it is /part/ of the problem we're trying to solve! And sometimes you can't neatly get around it: enum {a,b,c=y,d}; enum {w=b,x,t,z}; You can't reorder these. And you can't split them up if a,b,c,d and w,x,y,z belong together, and you still want to rely on auto-increment. But it's easy to see that a,b,c,d should be 0,1,3,4 and w,x,y,z is 1,2,3,4 (see sig). Any 'solutions' will spoil the code. > Co-recursive functions are a rarity in code. Co-recursion has some technical meaning which I'm not sure is the one that is relevant here. If you mean that A() calls B() which calls A(), then I write such code all the time. > separate prototype declarations in C. For people who like that code > arrangement, C's methods are a little inconvenient. (As Paavo points > out, C++ no longer needs that if you feel it is an issue.) With an extra construct? Having this natively possible anywhere in a language, without having to worry about such things at all, is more desirable: E readexpr(void) { ... return readterm();} E readterm(void) { ... return readexpr();} > Mutually > dependent imports (circular imports) are an issue, but these can almost > always be avoided in your code structuring. I've had experience of this and often found it difficult to impossible. 99% of functions would fit into the hierarchy, but there were always odd ones that didn't. Trying to extract things out usually turned into a can of worms, and you ended up with obviously contrived code, ruining the tidy structure of your project. (My solutions tended to use ad hoc manual declarations, circumventing the module system, but the compiler could not check that my manual declaration matched the actual definition of a function.) Again, this itself turns into the problem that needs to be fixed. You should be able to just write things in the most natural manner. If it makes sense to the person reading or writing the code, it should make sense to a compiler. -- bart enum (a=0,b,c=y,d) # usually 1-based enum (w=b,x,y,z) println a,b,c,d, w,x,y,z Output: 0 1 3 4 1 2 3 4 This however doesn't work: enum (a=b, b=a) |
"Öö Tiib" <ootiib@hot.ee>: Jan 31 06:42AM -0800 On Thursday, 31 January 2019 13:47:41 UTC+2, James Kuyper wrote: > completely independent of the distinction between "prototyped > declaration" and "non-prototyped declaration" (with the latter appearing > only in C). The "prototypes" are typically denoting alternative to "classes" in OOP languages with dynamic types. There instead of inheritance we just extend objects directly and instead of instantiations of classes we just clone prototype objects. That has not much to do with C or C++, closest such language is JavaScript. |
David Brown <david.brown@hesbynett.no>: Jan 31 04:38PM +0100 On 31/01/2019 12:47, James Kuyper wrote: > completely independent of the distinction between "prototyped > declaration" and "non-prototyped declaration" (with the latter appearing > only in C). Fair enough - that is a lot more precise than I was (and, I think more precise than necessary). I referred to "prototypes" merely because some people like to give a function prototype as a forward declaration, and then omit the function parameters (if any) later in the definition. |
David Brown <david.brown@hesbynett.no>: Jan 31 04:50PM +0100 On 31/01/2019 13:06, Bart wrote: > trying to solve! And sometimes you can't neatly get around it: > enum {a,b,c=y,d}; > enum {w=b,x,t,z}; It solves it for functions and types. It has never occurred to me that anyone would have need of re-ordering enums like that. I think it could be hard to get any solution here that does not involve multiple rounds or general equation solving, which is hardly appropriate for a language like C or C++. (You can do it in metafont or metapost, but those are very different kinds of language.) > Co-recursion has some technical meaning which I'm not sure is the one > that is relevant here. If you mean that A() calls B() which calls A(), > then I write such code all the time. Mutual recursion is the term I wanted. There can be cases where this is useful, in handling recursive data structures, but I think if you are writing it a lot you have questionable coding structures. (Not necessarily wrong, merely questionable.) However, the point is that is only with such mutual recursion that you need to have forward declarations for your functions - and it is not a hardship to use this on occasion. It would be annoying to have to use forward declarations for a large proportion of functions, but not for just a few. > desirable: > E readexpr(void) { ... return readterm();} > E readterm(void) { ... return readexpr();} I quite agree that it would be convenient to be able to do this without forward declarations, and I can well understand allowing it in a new language. I just don't think it is a big issue - like many people, I have programmed in C (and other languages that need forward declarations) for many years without feeling this to be a concern. >> Mutually dependent imports (circular imports) are an issue, but these >> can almost always be avoided in your code structuring. > I've had experience of this and often found it difficult to impossible. Maybe you have a fundamentally different way of organising code than I do. (I know we have quite different types of code). It simply doesn't occur in my coding - either embedded C, C++ and assembly programming, or PC programming in Python, Pascal, etc. |
jameskuyper@alumni.caltech.edu: Jan 31 08:02AM -0800 On Thursday, January 31, 2019 at 10:38:30 AM UTC-5, David Brown wrote: > precise than necessary). I referred to "prototypes" merely because some > people like to give a function prototype as a forward declaration, and > then omit the function parameters (if any) later in the definition. Could you demonstrate the technique you're talking about? I suspect that you've not describing it correctly. If function parameters are present in a forward declaration of a function, but omitted from the corresponding function definition, then: 1. In C++ you've defined an overload of the function with a different signature from the one used in the forward declaration - calling the function with arguments that match the forward declaration would result in a search (which would presumably fail) for a different overload. 2. In C, you've defined a function that's incompatible with the forward declaration. That's a constraint violation if they have the same scope (6.7p3), and the behavior is undefined (6.2.7p2), regardless of scope. |
Bart <bc@freeuk.com>: Jan 31 08:42PM On 31/01/2019 15:50, David Brown wrote: > Mutual recursion is the term I wanted. There can be cases where this is > useful, in handling recursive data structures, but I think if you are > writing it a lot you have questionable coding structures. No it's not questionable. Most of the big programs I've written have involved recursive data. (CAD systems, windows-based GUIs, compilers and interpreters. Even file systems are recursive.) Obviously yours don't. (Not > declarations for your functions - and it is not a hardship to use this > on occasion. It would be annoying to have to use forward declarations > for a large proportion of functions, but not for just a few. I had to do that for years. I can tell you that things are much sweeter if you don't have to bother. (It's quite a problem too if you have one language which or may not need forward declarations that has to be expressed in one which has its own rules for them.) > language. I just don't think it is a big issue - like many people, I > have programmed in C (and other languages that need forward > declarations) for many years without feeling this to be a concern. I like to add functions in any order. I shouldn't have to consider that the functions one may call are always defined earlier, or that the functions that might call this one must be defined later. How do you even find that spot in a busy module? And you might want to move things around, or copy code between files. >> I've had experience of this and often found it difficult to impossible. > Maybe you have a fundamentally different way of organising code than I > do. Let's take one project of mine (not C code obviously as it uses modules), and look at two modules mc_name and mc_type (two successive passes of a compiler). mc_name has this at the top: import mc_type And mc_type has this: import mc_name. Mutual imports. According to you, I should be able to trivially fix that. Those modules ought to be independent, but sometimes things aren't perfect. mc_name calls one function in mc_type, but I can't just extract that into a third module, as it has numerous connections to the rest of the module. And it's the same story the other way. And unless I have /two/ extra new modules, I would be mixing up the gubbins from what are supposed to be two unrelated modules, and exposing even more stuff that is supposed to be kept private to each. One more project where the two modules are cc_lex and cc_lib (a C compiler). And it's the same thing where rearranging things so that the modules are a pure hierarchy would mean tearing the project apart and having a weird module structure that now needs an explanation. (As I said, I solved this in the past by just adding a few manual function declarations to cut across module demarcations. Now it is easier for them just to import each other. It works fine.) |
Melzzzzz <Melzzzzz@zzzzz.com>: Jan 31 09:07PM > No it's not questionable. Most of the big programs I've written have > involved recursive data. (CAD systems, windows-based GUIs, compilers and > interpreters. Even file systems are recursive.) Obviously yours don't. List is recursive data structure, so as tree and any graph for that matter... are you sure you are arguing right thing? -- press any key to continue or any other to quit... |
Thomas Koenig <tkoenig@netcologne.de>: Jan 31 09:17PM >> https://vector-of-bool.github.io/2019/01/27/modules-doa.html >> Cool, the author compared C++ to Fortran ! > Not in a way that said something good about C++ modules. :( Not that there are a lot of good things to be said about the C++ module proposal. The question of which module is defined in which file (well, you could put it into a Makefile when you write it) is only one aspect. Another aspect is the question of how to handle #defines which are in force when a module is used... |
Bart <bc@freeuk.com>: Jan 31 09:42PM On 31/01/2019 21:07, Melzzzzz wrote: >> interpreters. Even file systems are recursive.) Obviously yours don't. > List is recursive data structure, so as tree and any graph for that > matter... are you sure you are arguing right thing? In the sorts of languages we're talking about, you would probably use iteration for lists and recursion for anything that looks like a tree because those would be the most practical choices. But if you are going to add lists to the set of recursive data structures, then that would just increase the number of programs that use mutual recursion. |
Melzzzzz <Melzzzzz@zzzzz.com>: Jan 31 10:33PM > But if you are going to add lists to the set of recursive data > structures, then that would just increase the number of programs that > use mutual recursion. Yeah list is first class citizen in recursive languages. -- press any key to continue or any other to quit... |
"Öö Tiib" <ootiib@hot.ee>: Jan 31 01:34AM -0800 On Wednesday, 30 January 2019 19:52:01 UTC+2, Daniel wrote: > pedantry and usefulness, yet those decisions make the difference between a > product that is accepted, and one that is not. Your comments appreciated, as > always. I forgot to tell that if you want to support wide variety of texts in interface like ...: auto s = j.as<std::basic_string<AnyChar,AnyTraits,AnyAllocator>>(); ... then that might be is too ambitiously configurable in call site. What it has to do may be very different based on what is the asked as return type and how type of j was configured, what is platform and compiler defines. So interface like ... auto a = j.to_utf8(); auto b = j.to_ucs4(); auto c = j.to_nsstring(); auto d = j.to_qstring(); auto e = j.to_bstr(); ... can be extended piece by piece and on need or feature request basis and can even refuse to compile on each platform or with every set of switches. Say NSString makes sense only on OSX/iOS, _bstr_t only in Windows and QString only when Qt is used. That might simplify the issue for all of writers, testers, profilers and callers of those and that will help to concentrate on those interested and provide value faster to them. |
Daniel <danielaparker@gmail.com>: Jan 31 07:06AM -0800 On Thursday, January 31, 2019 at 4:34:14 AM UTC-5, Öö Tiib wrote: > ... can be extended piece by piece and on need or feature request > basis Good advise, generally. Anyway, I've decided not to continue with experimental version (**). I've concluded that the experimental version would benefit no users, would annoy some, and would introduce the possibility of encoding exceptions everywhere instead of just at the endpoints. Daniel |
Vir Campestris <vir.campestris@invalid.invalid>: Jan 31 09:46PM On 28/01/2019 15:24, Scott Lurndal wrote: > of the hardware and test software. No spinning rust can provide those datarates; you have > to go to high end NVMe SSD setups. Do include measurements of the system overhead > when compared with using lower-overhead I/O mechanisms like mmap or O_DIRECT. Scott if his speeds are unbelieveably fast for his hardware - maybe he is running out of cache. But so what? It means he isn't bound by the hardware, and they are reflecting his I/O overheads. Andy |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 31 02:07AM +0100 On 30.01.2019 17:59, Richard wrote: >> through the odd spammer's comment, but not so much that it's a problem. > I've had very good results rejecting spam through wordpress.com, so it > is possible to configure wordpress to be very good at rejecting spam. Oh. I didn't even know one could do that. Re the code I posted it was ugly, just the first the worked, unreasonably half-way between two reasonable solutions. For consecutive enum values it would be simpler and more efficient to generate a `switch`. And for the case of wanting two-way conversion or ability to iterate over value/string pairs, the collection of value/string pairs should be provided on its own and not just a local static in a function. The OP has still not turned on commentary, but has posted summaries and one full quote of commentary he's received on Reddit. That approach did /not/ work out well. I mentioned, in the posting up-thread, that lack of commentary function on the blog could lead to > incorrect stuff will not be corrected, improvements and alternatives > will not be available and just that has happened. :( In particular, the January 27 posting "shrink_to_fit that doesn't suck" still provides only solutions (to a non-existing problem) that do suck, and the January 30 posting "What happens when we "new"" incorrectly and misleadingly states that when one writes T* t1 = new T; the compiler allegedly translates that to (really, it does NOT force use of the global allocation function) T* t2 = (T*)::operator new(sizeof(T)); try { new (t2) T; } catch(...) { ::operator delete(t2); throw; } The incorrect belief in that correspondence was once the basis of an infamous bug in Microsoft's MFC framework, where one could get a memory leak that manifested only in debug builds. So, it seems we have a new C++ blog that provides some misleading dis-information, sort of like Herb Schildt, with commentary turned off. :( Cheers!, - Alf |
mvorbrodt@gmail.com: Jan 30 06:00PM -0800 On Wednesday, January 30, 2019 at 8:08:11 PM UTC-5, Alf P. Steinbach wrote: > dis-information, sort of like Herb Schildt, with commentary turned off. :( > Cheers!, > - Alf the comments are open on the blog. please post corrections. if I put misleading information I want to learn and correct it. |
mvorbrodt@gmail.com: Jan 30 06:01PM -0800 On Tuesday, January 29, 2019 at 10:23:53 PM UTC-5, Alf P. Steinbach wrote: > -------------------------------------------------------------------------- > Cheers!, > - Alf the comments are open on the blog. please post corrections. if I put misleading information I want to learn and correct it. |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment