- Rust has the same memory problem as C and C++ - 11 Updates
- template operator<< - 5 Updates
- std::filesystem::copy_options::overwrite_existing throws - 3 Updates
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. |
No comments:
Post a Comment