Sent from my iPad
Begin forwarded message:
From: Sharon Kahn <sharon62kahn@gmail.com>
Date: April 30, 2020 at 7:03:14 PM CDT
Subject: Fwd: Dancing... of an unusual sort
From: Sharon Kahn <sharon62kahn@gmail.com>
Date: April 30, 2020 at 7:03:14 PM CDT
Subject: Fwd: Dancing... of an unusual sort
Juha Nieminen <nospam@thanks.invalid>: Apr 30 06:19AM > (IMHO both C and C++ should have made internal linkage the default for > all data and functions from the start, and required an explicit "extern" > for external linkage, but it's far too late to fix that!) I think that there's a slight problem with that in that if you define a const variable in a header file, if it has internal linkage by default, it will be duplicated in every compilation unit where it's used (unless the compiler can "inline" it). This *is* actually a slight problem in C++, IMO. It's easy to put something like namespace MySpace { const std::vector<int> values = { 1, 2, 3, 4 }; } in a header file without realizing that the vector will be duplicated in all compilation units where it's used, and thus duplicated that many times in the executable binary (unless the compiler somehow optimizes this). Of course nowadays we can declare it as 'inline' which solves the problem, but that has to be explicitly specified, and it needs compiler support. |
Melzzzzz <Melzzzzz@zzzzz.com>: Apr 30 06:57AM > in the executable binary (unless the compiler somehow optimizes this). > Of course nowadays we can declare it as 'inline' which solves the problem, > but that has to be explicitly specified, and it needs compiler support. What's difference if `inline`? -- current job title: senior software engineer skills: c++,c,rust,go,nim,haskell... press any key to continue or any other to quit... U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec Svi smo svedoci - oko 3 godine intenzivne propagande je dovoljno da jedan narod poludi -- Zli Zec Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi bili naoruzani. -- Mladen Gogala |
David Brown <david.brown@hesbynett.no>: Apr 30 09:20AM +0200 On 30/04/2020 08:19, Juha Nieminen wrote: > const variable in a header file, if it has internal linkage by default, > it will be duplicated in every compilation unit where it's used (unless > the compiler can "inline" it). You put const definitions in a header if you are happy to have them duplicated - if not, you put the definition and initialisation in a single file and make the "const" external. The C++ "default to static" rule for const is so that you can easily use "const int noOfThings = 4;" instead of C-style "#define noOfThings 4". The expectation is that the const objects defined in a header have less than zero cost - they don't take up space, they don't require run-time initialisation, and they get folded into code just like a literal constant. If you are putting large "const" data in headers, then surely you /know/ that this will may take duplicate space? It can still be a useful thing that people want to do - hence the trick of using static members in a template, and then the much nicer step of adding inline variables to the language. > in a header file without realizing that the vector will be duplicated in > all compilation units where it's used, and thus duplicated that many times > in the executable binary (unless the compiler somehow optimizes this). Do people do this sort of thing without realising the consequences? |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Apr 30 07:58AM On Thu, 2020-04-30, David Brown wrote: > On 30/04/2020 08:19, Juha Nieminen wrote: ... >> all compilation units where it's used, and thus duplicated that many times >> in the executable binary (unless the compiler somehow optimizes this). > Do people do this sort of thing without realising the consequences? Looks like something I might easily do. I'm weak in this area (but not weaker than my coworkers, I think). /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
David Brown <david.brown@hesbynett.no>: Apr 30 01:01PM +0200 On 30/04/2020 09:58, Jorgen Grahn wrote: >> Do people do this sort of thing without realising the consequences? > Looks like something I might easily do. I'm weak in this area (but > not weaker than my coworkers, I think). Perhaps it is just that for my type of work, I think about such efficiencies all the time - and thus don't make that kind of mistake. (I make other mistakes instead :-) ) |
Tim Rentsch <tr.17687@z991.linuxsc.com>: Apr 30 04:49AM -0700 > One curious difference between C and C++, which I only learned the > details of recently, is the difference in semantics of a const > variable at the global scope. [elaboration] Right. I did actually think of this one, but it didn't pop up in my test compiles so I forgot to include it. |
Tim Rentsch <tr.17687@z991.linuxsc.com>: Apr 30 04:59AM -0700 > Since C libraries often use more than just function declarations, > C++ still needs to support eg. C style structs, typedefs, etc. > Breaking compatibility with C libraries would be a huge setback. What I would like to see is for C++ to define how extern "C" blocks work so that inside extern "C" { ... } what is accepted is C syntax, and for that part of the source uses C semantics. If this were done it is then trivial to write C headers that C++ can #include, and guaranteed that what they do in C++ is the same as what they do in C. Since it is C++ that wants to include C headers, and not the other way around, it is C++ that should more of the heavy lifting needed to get that to happen. |
Tim Rentsch <tr.17687@z991.linuxsc.com>: Apr 30 05:08AM -0700 > Since C libraries often use more than just function declarations, > C++ still needs to support eg. C style structs, typedefs, etc. > Breaking compatibility with C libraries would be a huge setback. Postscript: I wouldn't mind adding a construct in C so that extern "C" { ... } were accepted as C source, with the same effect as leaving off the enclosing tokens. Surely it is almost no effort to add such a rule to the language, and it would make writing C++-compatible headers even easier. This idea, coupled with the suggestion given in my other posting, is all that is needed to "harmonize" C and C++ as far as headers are concerned. |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Apr 30 07:53PM On Thu, 2020-04-30, David Brown wrote: >> not weaker than my coworkers, I think). > Perhaps it is just that for my type of work, I think about such > efficiencies all the time - and thus don't make that kind of mistake. That's surely part of it: I work with large and old programs where the worst inefficiencies are in the I/O, and the other inefficiencies are lost in the background noise. (Although in a recent hobby project, I kicked out std::regex when I noticed it doubled the code segment size.) > (I make other mistakes instead :-) ) /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Apr 30 02:18PM -0700 Tim Rentsch <tr.17687@z991.linuxsc.com> writes: [...] > in C. Since it is C++ that wants to include C headers, and not the > other way around, it is C++ that should more of the heavy lifting > needed to get that to happen. Interesting idea, but I'm not convinced that requiring C++ compilers to handle extern "C" { int *class = malloc(sizeof 'A'); } would be worth the implementation effort. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */ |
James Kuyper <jameskuyper@alumni.caltech.edu>: Apr 30 07:19PM -0400 Tim Rentsch <tr.17687@z991.linuxsc.com> writes: [...] > in C. Since it is C++ that wants to include C headers, and not the > other way around, it is C++ that should more of the heavy lifting > needed to get that to happen. Interesting - that would turn a popular misconception into reality, which might qualify as an argument in favor of the idea. However, code inside an extern "C" {} block has had C++ semantics for at least as long as those semantics have been different from C semantics (early versions of C++ were simply "C with classes" - the semantics weren't very different at that time). As a result, a fair amount of code has been written that either accidentally or intentionally depends upon that fact. As a result, such a change would probably break a fair amount of existing code. There's another closely related problem. I get the impression that you're thinking primarily in terms of using extern "C" function declarations in C++ code to give that C++ code the ability to call functions implemented in C. However, you're also allowed to provide extern "C" definitions for C++ functions that are callable from C. I'm assuming, in particular, that "C semantics" would prohibit calling functions declared with other language linkages. If that's not the case, you need to more precisely specify what you mean by "C semantics". If the C++ standard were modified as you describe, how could such code be re-written? |
Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo>: Apr 29 10:47PM -0400 Vir Campestris wrote: > (I'd be happier if the parameter was a Collection<Object> for better type safety) > Any ideas? > Andy This seems to work for me: #include <iostream> #include <vector> #include <list> using namespace std; struct Object { }; ostream& operator<<(ostream &os, const Object &o) { return os << "Object " << (void*)&o; } vector<Object> vec{Object(), Object()};; list<Object> lst{Object(), Object(), Object()}; template <typename Collection, typename T = typename Collection::value_type> ostream& operator<<( ostream& o, const Collection& objects) { for (const T & e: objects) o << e << '\t'; return o; } int main(int, char*[]) { cout << vec << ' ' << lst << endl; return 0; } |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 30 06:39AM +0200 On 30.04.2020 04:47, Pavel wrote: > cout << vec << ' ' << lst << endl; > return 0; > } Detecting that a type is a collection type, without false positives, is difficult. Consider that e.g. `std::is_same` is an `std::integral_constant<bool, V>` with V either `true` or `false`. This is a type with a `value_type`, and implicit conversion to `bool`: ---------------------------------------------------------------- #include <iostream> #include <type_traits> using namespace std; auto main() -> int { cout << boolalpha; cout << is_same<short, short>() << endl; // "true" cout << is_same<short, long>() << endl; // "false" } ---------------------------------------------------------------- But with your `operator<<` template in the picture it will be selected to output those `std::integral_constant` instances, and treating those instances as collections will just fail to compile. So, instead, check for the features that are actually used. The following appears to work for standard library collections: template <typename Collection, typename T = typename Collection::const_iterator> ostream& operator<<( ostream& o, const Collection& objects) { for (const auto& e: objects) o << e << '\t'; return o; } However, for a more general solution I think I would define a general thin wrapper type à la `std::reference_wrapper` to use as argument, and let the client code explicitly specify (via use of that wrapper type) that it wants to invoke the for-collections overload of `<<`. Simply, explicit = good, implicit = not so good, in general. - Alf |
Juha Nieminen <nospam@thanks.invalid>: Apr 30 06:24AM > Detecting that a type is a collection type, without false positives, is > difficult. Would C++20 concepts help here? |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 30 01:10PM +0200 On 30.04.2020 08:24, Juha Nieminen wrote: >> Detecting that a type is a collection type, without false positives, is >> difficult. > Would C++20 concepts help here? I hope so. But I don't know. Sorry. - Alf |
Vir Campestris <vir.campestris@invalid.invalid>: Apr 30 09:26PM +0100 On 30/04/2020 05:39, Alf P. Steinbach wrote: > thin wrapper type à la `std::reference_wrapper` to use as argument, and > let the client code explicitly specify (via use of that wrapper type) > that it wants to invoke the for-collections overload of `<<`. It's a little hacky project I'm doing purely for my own amusement. It doesn't need to be clean really :) But thank you both. It was annoying me! Andy |
Ralf Goertz <me@myprovider.invalid>: Apr 30 03:46PM +0200 Hi, I just noticed that std::filesystem::copy_options::overwrite_existing doesn't have an effect using gcc 9.3.0 under windows but works fine under linux. That is, the program #include <filesystem> int main() { std::filesystem::copy_file("foo","bar",std::filesystem::copy_options::overwrite_existing); } throws with terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error' what(): filesystem error: cannot copy file: File exists [foo] [bar] provided that the regular files "foo" and "bar" exist. Under linux this only happens if I omit the copy option. Since this is such a trivial thing and I don't find any reports on gcc's bugzilla I wonder if this behaviour is standard conforming. But then there is also nothing on cpprefererence.com on that (AFAICT). Can this really be a bug? |
James Kuyper <jameskuyper@alumni.caltech.edu>: Apr 30 10:37AM -0400 On 4/30/20 9:46 AM, Ralf Goertz wrote: > thing and I don't find any reports on gcc's bugzilla I wonder if this > behaviour is standard conforming. But then there is also nothing on > cpprefererence.com on that (AFAICT). Can this really be a bug? The standard only allows an implementation to "Report a file already exists error as specified in 30.10.7 if: (4.1.1) — !is_regular_file(from), or (4.1.2) — exists(to) and !is_regular_file(to), or (4.1.3) — exists(to) and equivalent(from, to), or (4.1.4) — exists(to) and (options & (copy_options::skip_existing | copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none" Do any of those possibilities apply? If not, it's a bug. |
Paavo Helde <eesnimi@osa.pri.ee>: Apr 30 10:58PM +0300 30.04.2020 16:46 Ralf Goertz kirjutas: > thing and I don't find any reports on gcc's bugzilla I wonder if this > behaviour is standard conforming. But then there is also nothing on > cpprefererence.com on that (AFAICT). Can this really be a bug? FWIW, compiling this program with my Cygwin gcc 9.3.0 in Windows works as expected (copies the file). Note that in Windows the files may be easily locked by other programs (including non-obvious ones like virus scanners) so that they cannot be deleted (though in this case the error message should probably be something like "Access denied"). In Unix world file deletion means just a refcount drop in inode which has a much better chance to succeed. To cope with that deficiency there is even a special Windows feature (MoveEx) to schedule files for deletion on next restart. |
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. |
Amine Proffet <amineisthetrueprophetofgod@gmail.com>: Apr 29 10:20PM -0700 > The only thing I believe is that you don't have any sex. Amine is a prophet of God! He does not partake in whimsical fancies of flesh! |
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.programming.threads+unsubscribe@googlegroups.com. |
Vir Campestris <vir.campestris@invalid.invalid>: Apr 29 09:49PM +0100 I've got a bit of code where I want to serialise collections of Objects. I have for example std::vector<Object> vec; std::list<Object> lst; It seems to me as if I should be able to write an operator<< to write them out something like template <typename Collection> std::ostream& operator<<( std::ostream& o, const Collection& objects) { for (auto e:objects) o << e << '\t'; return o; } But I can't find a syntax that works. That one above will build - except then the compiler can't work out which operator<< to use. I'm not convinced it's even considering that one. (I'd be happier if the parameter was a Collection<Object> for better type safety) Any ideas? Andy |
Juha Nieminen <nospam@thanks.invalid>: Apr 29 08:01AM > there is some sort of significant common ground between them. > Thirty years ago there was, but now there isn't, and it's time to > move on. At a very minimum enough compatibility would be good to maintain that C libraries can be used directly from C++ (with a simple extern "C" {} declaration of the C stuff). Since C libraries often use more than just function declarations, C++ still needs to support eg. C style structs, typedefs, etc. Breaking compatibility with C libraries would be a huge setback. |
Juha Nieminen <nospam@thanks.invalid>: Apr 29 08:10AM > Certainly there are ones I didn't think of until just recently > when I ran a piece of C code through a C++ compiler. Some of > the obvious problems: One curious difference between C and C++, which I only learned the details of recently, is the difference in semantics of a const variable at the global scope. For example, if you have this in one compilation unit: extern const char* const gName; and this in another compilation unit: const char* const gName = "Name"; and try to use that gName in that first compilation unit, in C it will compile fine, but in C++ you'll get a linker error about "gName" not being found. The reason for this is that in C a const at the global scope has external linkage by default, while in C++ it has internal linkage. In other words, in C++ const char* const gName = "Name"; is the same thing as static const char* const gName = "Name"; while in C it's not. In order to define that variable with external linkage in C++ you have to say it explicitly: extern const char* const gName = "Name"; (The same is true for consts inside a namespace. In this case "global scope" also means "namespace scope".) |
David Brown <david.brown@hesbynett.no>: Apr 29 11:15AM +0200 On 29/04/2020 10:10, Juha Nieminen wrote: > extern const char* const gName = "Name"; > (The same is true for consts inside a namespace. In this case "global scope" > also means "namespace scope".) Yes. But this is easily solved by the common practice of declaring any data that needs external linkage with an "extern" declaration in a header file, and including that header both from the file that defines the object, and any file that uses it. (IMHO both C and C++ should have made internal linkage the default for all data and functions from the start, and required an explicit "extern" for external linkage, but it's far too late to fix that!) |
Lynn McGuire <lynnmcguire5@gmail.com>: Apr 28 07:43PM -0500 On 4/28/2020 6:04 PM, Ian Collins wrote: >> I like explicitly initializing variables since I have been so burned in >> the past. Just an old Fortran hacker writing C++. > What did your "expert" claim is wrong with the code? The string and int initializations were not allowed. Others in the above postings said those came about in the C++2011 spec. Lynn | |||||||||||||||||||||||||||||||||||||
Ian Collins <ian-news@hotmail.com>: Apr 29 12:47PM +1200 On 29/04/2020 12:43, Lynn McGuire wrote: >> What did your "expert" claim is wrong with the code? > The string and int initializations were not allowed. Others in the > above postings said those came about in the C++2011 spec. Okay, so Juha's guess was on the money! -- Ian. | |||||||||||||||||||||||||||||||||||||
Lynn McGuire <lynnmcguire5@gmail.com>: Apr 28 08:54PM -0500 On 4/28/2020 7:47 PM, Ian Collins wrote: >> The string and int initializations were not allowed. Others in the >> above postings said those came about in the C++2011 spec. > Okay, so Juha's guess was on the money! I am sorry that I did not make that clear. And I got hung out by my Open Watcom pre C++2011 compiler which refused the class variable initializations. So I got to put in a #ifndef. Lovely. class ExcelSelection { public: #ifndef __WATCOMC__ std::string spreadsheetName = ""; std::string sheetName = ""; std::string beginRow = ""; std::string beginColumn = ""; std::string endRow = ""; std::string endColumn = ""; bool isRange = false; #else std::string spreadsheetName; std::string sheetName; std::string beginRow; std::string beginColumn; std::string endRow; std::string endColumn; bool isRange; Tuesday, April 28, 2020Digest for comp.lang.c++@googlegroups.com - 15 updates in 3 topics
Digest for comp.programming.threads@googlegroups.com - 3 updates in 3 topics
Monday, April 27, 2020Digest for comp.lang.c++@googlegroups.com - 2 updates in 1 topic
Digest for comp.programming.threads@googlegroups.com - 2 updates in 2 topics
Sunday, April 26, 2020Digest for comp.lang.c++@googlegroups.com - 10 updates in 4 topics
Subscribe to:
Posts (Atom)
Blog Archive
About Me |