- std::copy with std::ostream_iterator<std::array...> - 4 Updates
- Union type punning in C++ - 4 Updates
- Write to file in 8 places simultaneously - 4 Updates
- Don't be fooled by cpp.sh - 9 Updates
- C++ threshold for "stupid" sorting algorithms (O(n^2)) - 1 Update
- invalid use of non-static member function - 1 Update
- Is there a way to determine endianess in a constexpr-function ? - 2 Updates
Ralf Goertz <me@myprovider.invalid>: Jan 02 10:37AM +0100 Hi, I don't get the problem in the following program. If I use using Coords=Foo; everything is okay but with using Coords=std::array<int,2> I get bombarded with (for me) undecipherable template errors originating from the std::copy line. Note that without that line it works for both types, so the operator overload "<<" should not be the problem. What ist going on #include <iostream> #include <iterator> #include <algorithm> #include <array> #include <set> struct Foo { int i,j; bool operator<(const struct Foo &r) const { //needed for set if (i<r.i) return true; return j<r.j; } }; std::ostream & operator<<(std::ostream &o,const std::array<int,2> &c) { return o<<'('<<c[0]<<','<<c[1]<<')'; } std::ostream & operator<<(std::ostream &o,const Foo &c) { return o<<'('<<c.i<<','<<c.j<<')'; } using Coords=Foo; //this works //using Coords=std::array<int,2>; //this doesn't int main() { std::set<Coords> ls; ls.insert(Coords({47,11})); std::cout<<*ls.begin()<<std::endl; std::copy(ls.cbegin(),ls.cend(),std::ostream_iterator<Coords>(std::cout," ")); //Compile error with array std::cout<<"\n"; } |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 02 12:27PM +0200 On 2.01.2020 11:37, Ralf Goertz wrote: > I get bombarded with (for me) undecipherable template errors originating > from the std::copy line. Note that without that line it works for both > types, so the operator overload "<<" should not be the problem. Your example starts to compile if you put the relevant operator<< inside namespace std. |
Bo Persson <bo@bo-persson.se>: Jan 02 12:26PM +0100 On 2020-01-02 at 10:37, Ralf Goertz wrote: > I get bombarded with (for me) undecipherable template errors originating > from the std::copy line. Note that without that line it works for both > types, so the operator overload "<<" should not be the problem. But it is. :-) Argument dependent lookup will search for an operator in the namespace(s) of the arguments (thus its name :-). If you (or a standard algorithm) use an operator<< with two types from namespace std (for example, std::ostream and std::array), the compiler will look for an operator<< also in namespace std. There are lots of them, but none for std::array. Your operator is in the global namespace, but std::array is not. So that operator will not be found. It works for Foo, because the type and the operator are in the same namespace. |
Ralf Goertz <me@myprovider.invalid>: Jan 02 04:10PM +0100 Am Thu, 2 Jan 2020 12:26:59 +0100 > that operator will not be found. > It works for Foo, because the type and the operator are in the same > namespace. Thanks for the explanation. I figured as much after having read Paavo's reply. But two questions remain. First, I thought it would be illegal (or at least frowned upon) for user code to inject anything into the std namespace. And what is the difference for the line std::cout<<*ls.begin()<<std::endl; (ls being of type std::set<std::array<int,2>>) although I have defined the operator in the global namespace and both operands are in std (I guess). Shouldn't the rule you quoted also lead to a lookup failure? |
boltar@nowhere.org: Jan 02 09:36AM On Wed, 1 Jan 2020 19:24:26 +0000 >Undefined behaviour aside is C++ union type punning an acceptable hack or not, >given that it is legal in C? Using a union or otherwise, type punning in a necessity when doing low level programming. If C++ is ever to be used in this scenario then it has to be Supported. |
"Öö Tiib" <ootiib@hot.ee>: Jan 02 03:34AM -0800 On Wednesday, 1 January 2020 21:24:19 UTC+2, Mr Flibble wrote: > If it works on all the compilers I care about does it really matter that it is *currently* classed as undefined behaviour? > I would say that everyone has "secretly" fucking done it some time or other so the C++ Standards Committee should get there act together and legalize it like it has been in C. > Can anyone provide a straight answer to this? To me it seems to be unneeded feature. 1) Experiments of mine and others have shown that usage of memcpy instead of other ways of type punning tends to generate better or same codes. It is hard to find examples where other methods are really beneficial. Can the "defacto" gang provide any? No? I thought so. 2) Compiler writers say that type punning with union breaks some aliasing optimizations so they have to pessimize just for a case. I haven't studied all details of such claims but as they are very highly skilled people I trust them. 3) Whole pile of different methods is unneeded for doing low level bit hacks. By Principle of Least Astonishment it is advisable to do those hacks always using same idioms even when there are multiple different ways available. So whatever way the committees of C and C++ decide I will continue to use memcpy myself for type punning and I will continue to suggest that as rule in coding standards of projects where I participate. That old blog says basically same thing as me: <https://blog.regehr.org/archives/959> |
Bo Persson <bo@bo-persson.se>: Jan 02 12:49PM +0100 On 2020-01-02 at 12:34, Öö Tiib wrote: > that as rule in coding standards of projects where I participate. > That old blog says basically same thing as me: > <https://blog.regehr.org/archives/959> The C++ committee seems unwilling to change the union rules and so instead adds a bit_cast function to package the memcpy usage with a slightly better name: template< class To, class From > constexpr To bit_cast(const From& from) noexcept; https://en.cppreference.com/w/cpp/numeric/bit_cast Bo Persson |
"Öö Tiib" <ootiib@hot.ee>: Jan 02 04:52AM -0800 On Thursday, 2 January 2020 13:49:39 UTC+2, Bo Persson wrote: > template< class To, class From > > constexpr To bit_cast(const From& from) noexcept; > https://en.cppreference.com/w/cpp/numeric/bit_cast Thanks, I didn't somehow even notice that. So we can throw away our own type punning wrappers around memcpy in C++20. |
Frederick Gotham <cauldwell.thomas@gmail.com>: Jan 02 01:46AM -0800 First, let me give an example of code I wrote this morning to write to RAM in 8 places simultaneously: unsigned constexpr g_amount_threads = 8; #include <cstddef> using std::size_t; #include <cstdint> /* uint8_t, uint64_t */ #include <numeric> /* iota */ #include <thread> /* thread */ typedef std::uint8_t Element_Type; size_t constexpr g_total_bytes = 4294967296ull; // Four gigabytes size_t constexpr g_total_elements = g_total_bytes / sizeof(Element_Type); size_t constexpr g_elements_per_thread = g_total_elements / g_amount_threads; Element_Type *g_p_mem = nullptr; void Thread_Entry_Point_Set_Memory(unsigned const thread_number) { Element_Type *const p = g_p_mem + (g_elements_per_thread * thread_number); Element_Type *const q = p + g_elements_per_thread; std::iota(p, q, static_cast<Element_Type>(g_elements_per_thread * thread_number)); } #include <iostream> using std::cout; using std::endl; auto main(void) -> int { g_p_mem = new Element_Type[g_total_elements]; std::thread *ptrs_threads[g_amount_threads]; for (unsigned i = 0; i != g_amount_threads; ++i) { ptrs_threads[i] = new std::thread(Thread_Entry_Point_Set_Memory,i); } // Now join all the threads for (auto &p : ptrs_threads) { p->join(); delete p; } delete [] g_p_mem; } I have measured the differences in execution time with 1 thread, with 2 threads, with 4 threads, etc.. What I want to do now is create a very large file (4 GB) on the hard disk and write to it in 8 different places simultaneously. I know that I can create 8 different files and deal with them independently, but I just want one file. I think this would be possible under Unix using the POSIX functions open, pwrite, writenv. Has anyone tried it? |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 02 12:46PM +0200 On 2.01.2020 11:46, Frederick Gotham wrote: > delete [] g_p_mem; > } > I have measured the differences in execution time with 1 thread, with 2 threads, with 4 threads, etc.. This is basically testing the main memory throughput. For curiosity, what where the results? > What I want to do now is create a very large file (4 GB) on the hard disk and write to it in 8 different places simultaneously. I know that I can create 8 different files and deal with them independently, but I just want one file. And this is testing either main memory throughput or hard disk throughput, depending on the amount of free memory in the computer. > I think this would be possible under Unix using the POSIX functions open, pwrite, writenv. Has anyone tried it? If you aim for max speed and are willing to use non-portable code, you should probably consider mmap. |
Frederick Gotham <cauldwell.thomas@gmail.com>: Jan 02 03:32AM -0800 On Thursday, January 2, 2020 at 9:47:01 AM UTC, Frederick Gotham wrote: > I think this would be possible under Unix using the POSIX functions open, pwrite, writenv. Has anyone tried it? Making a few changes to my original code, here's what I have so far for writing to disk. I'm not getting consistent behaviour yet (the output files have a different sha256 sum depending on how many cores I use). Anyway here's what I have so far: unsigned constexpr g_amount_threads = 8; char const g_filepath[] = "/home/fgotham/special.txt"; #include <cstddef> using std::size_t; #include <cstdint> /* uint8_t, uint64_t */ #include <numeric> /* iota */ #include <thread> /* thread */ #include <stdio.h> /* fopen, fseek, fputc, fclose */ #include <iostream> using std::cout; using std::endl; /* The next three lines are for POSIX functions: open, pwrite, close */ #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> struct Thread_Local_Stuff { std::thread *ptr_thread; int fd; }; Thread_Local_Stuff g_thread_stuffs[g_amount_threads]; typedef std::uint8_t Element_Type; size_t constexpr g_total_bytes = 4294967296ull; // Four gigabytes size_t constexpr g_bytes_per_thread = g_total_bytes / g_amount_threads; size_t constexpr g_total_elements = g_total_bytes / sizeof(Element_Type); size_t constexpr g_elements_per_thread = g_total_elements / g_amount_threads; Element_Type *g_p_mem = nullptr; void Thread_Entry_Point(unsigned const thread_number) { Element_Type *const p = g_p_mem + (g_elements_per_thread * thread_number); Element_Type *const q = p + g_elements_per_thread; std::iota(p, q, static_cast<Element_Type>(g_elements_per_thread * thread_number)); pwrite( g_thread_stuffs[thread_number].fd, p, g_bytes_per_thread, p - g_p_mem ); } auto main(void) -> int { // First create the very large file FILE *pfile = fopen(g_filepath, "w"); fseek(pfile, g_total_bytes - 1u, SEEK_SET); fputc('\0', pfile); fclose(pfile); // Now start the threads g_p_mem = new Element_Type[g_total_elements]; for (unsigned i = 0; i != g_amount_threads; ++i) { g_thread_stuffs[i].fd = open(g_filepath, O_WRONLY|O_SYNC); g_thread_stuffs[i].ptr_thread = new std::thread(Thread_Entry_Point,i); } // Now join all the threads for (auto &e : g_thread_stuffs) { e.ptr_thread->join(); delete e.ptr_thread; close(e.fd); } delete [] g_p_mem; } |
Frederick Gotham <cauldwell.thomas@gmail.com>: Jan 02 03:34AM -0800 On Thursday, January 2, 2020 at 10:46:53 AM UTC, Paavo Helde wrote: > This is basically testing the main memory throughput. For curiosity, > what where the results? One thread is 12 seconds. Eight threads is 1.8 seconds. > And this is testing either main memory throughput or hard disk > throughput, depending on the amount of free memory in the computer. And depending on where the bottle necks are. > If you aim for max speed and are willing to use non-portable code, you > should probably consider mmap. I'm gonna play with the POSIX functions so more before I look up mmap. |
David Brown <david.brown@hesbynett.no>: Jan 01 11:09PM +0100 On 01/01/2020 01:16, Chris M. Thomasson wrote: >> Are you kidding? -Wall is one of the most basic options one always >> uses with gcc (together with -Wextra and a bunch of other warning flags). > Heck, what about -ansi and/or -pedantic... ;^) Don't use "-ansi" - it is a misnomer. Use the "-std" option of your choice. I would always recommend using "-std". If you are writing highly portable code, then "-Wpedantic" along with a suitable choice of "-std" is recommended. But not all code is supposed to be highly portable. If you are writing code with the intention of using only gcc, then there is no problem using "-std=gnu++17", or whatever you want, and using gcc extensions. It won't be standard C++, but you can take advantage of the extensions provided - this is your choice when you write your code. (There are many other commonly used options, like "-O2" or "-o" to give the output file name. But -Wall is still a very commonly used standard option.) |
boltar@nowhere.org: Jan 02 09:24AM On Wed, 01 Jan 2020 15:48:12 +0200 >members and one cannot cast it (e.g. via union type punning) to other >union type willy-nilly. >That's EXACTLY what everybody has tried to explain you for several days Really? Please state exactly where I ever suggested using unions for classes rather than just POD. >already: one is allowed to access ONLY the ACTIVE member of the union at >any time moment. A variant IS NOT a union, its simply a multi type single value container. The point of a union is to access MORE than 1 type without doing any sets in between. >Good that you are starting to understand it now. Perhaps you need to improve your English. You understand the words and grammar but you clearly don't always understand the intent. Don't worry , I have the same problem when speaking French - just understanding whats being said literally doesn't always help, n'est pas? |
boltar@nowhere.org: Jan 02 09:25AM On Wed, 01 Jan 2020 09:09:32 -0600 >>Variable length C99 arrays arn't in the C++ standard but I've yet to come >>across a C++ compiler that didn't support them either. >MSVC. Fair enough, but last time I used it a few years back MSVC didn't support some features of modern C++ either. |
boltar@nowhere.org: Jan 02 09:28AM On Wed, 1 Jan 2020 08:11:38 -0800 (PST) >e >> and read as another >Not according to K&R, 1st edition. K&R write Usage has changed since the early 1970s. We don't declare function parameters twice either any more. eg: main(argc, argv) int argc; char **argv; { } |
boltar@nowhere.org: Jan 02 09:33AM On Wed, 1 Jan 2020 23:15:56 +0100 >On 01/01/2020 10:13, boltar@nowhere.org wrote: >> Thats because there arn't any because all C++ compilers are also C compilers. >MSVC doesn't support modern C. It doesn't support all of modern C++ either so no surprises there. >to compile C++ code, it uses C++ semantics. When you use it for C code, >it uses C semantics. (And when you use it for Fortran, or Ada, it uses >those language semantics.) Fortran isn't a subset of Ada. >> Variable length C99 arrays arn't in the C++ standard but I've yet to come >> across a C++ compiler that didn't support them either. >gcc doesn't support them when you use it in standard modes. What gcc does and doesn't do is highly dependant on version. C99 support seems to be standard in the more recent versions and about time given the standard is now more than 20 years old. |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 02 12:02PM +0200 >> That's EXACTLY what everybody has tried to explain you for several days > Really? Please state exactly where I ever suggested using unions for classes > rather than just POD. The rules are the same, whether the union contains PODS or non-PODS. The only exception is about standard-layout structs that share a common initial sequence, which does not involve the type punning you are advocating. > A variant IS NOT a union, its simply a multi type single value container. The > point of a union is to access MORE than 1 type without doing any sets in > between. Something which is illegal by the standard cannot be "the point" of a standard feature. >> Good that you are starting to understand it now. > Perhaps you need to improve your English. And you need to improve your sarcasm detectors! |
boltar@nowhere.org: Jan 02 10:52AM On Thu, 02 Jan 2020 12:02:48 +0200 >> Really? Please state exactly where I ever suggested using unions for classes >> rather than just POD. >The rules are the same, whether the union contains PODS or non-PODS. The They might be the same but that doesn't mean using complex classes in unions is a good idea and I never advocated it. >> between. >Something which is illegal by the standard cannot be "the point" of a >standard feature. Where is it stated thats its illegal? >>> Good that you are starting to understand it now. >> Perhaps you need to improve your English. >And you need to improve your sarcasm detectors! Sarcasm doesn't work if YOU are the one who missed the point. |
David Brown <david.brown@hesbynett.no>: Jan 02 12:16PM +0100 >>> Thats because there arn't any because all C++ compilers are also C compilers. >> MSVC doesn't support modern C. > It doesn't support all of modern C++ either so no surprises there. It does rather well at supporting modern C++ standards. But its C support is limited to C90 - it does not even have proper C99. <https://en.cppreference.com/w/cpp/compiler_support> >> it uses C semantics. (And when you use it for Fortran, or Ada, it uses >> those language semantics.) > Fortran isn't a subset of Ada. C is not a subset of C++. >>> across a C++ compiler that didn't support them either. >> gcc doesn't support them when you use it in standard modes. > What gcc does and doesn't do is highly dependant on version. Not in this case. gcc has never supported VLA's in C++ when using standard modes, and never will - unless a later C++ standard incorporates VLA's. > C99 support seems > to be standard in the more recent versions and about time given the standard > is now more than 20 years old. I'm guessing you are referring to the standard used by gcc by default if you don't specify "-std". To get standard modes - aiming for closer conformance to a particular C or C++ standard - you need to specify the standard you want (along with -pedantic or -pedantic-errors). By default, you get a C or C++ standard with gcc extensions (currently gnu17 for C and gnu++14 for C++). |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 02 01:27PM +0200 >> Something which is illegal by the standard cannot be "the point" of a >> standard feature. > Where is it stated thats its illegal? You see, I'm not against making the union type punning legal for POD types, for C compatibility, as proposed by Mr Flibble in another thread. If and when this gets incorporated into the C++ standard, I will happily encourage it as it is a bit safer than some other type punning methods (at least it gets the alignments correct). However, for now this is UB by the standard, and "illegal" is a colloquial term often used for UB in technical standards. I used this term because it seems you cannot really grasp what UB is. >>> Perhaps you need to improve your English. >> And you need to improve your sarcasm detectors! > Sarcasm doesn't work if YOU are the one who missed the point. Amusing... |
Christian Gollwitzer <auriocus@gmx.de>: Jan 02 11:28AM +0100 Am 01.01.20 um 13:17 schrieb Soviet_Mario: > I did not mention that the algorithm HAS TO BE "stable" : not to move > equally ranked items (in order to allow tables to be sorted by multiple > keys) Do mergesort: it is inherently stable, rather simple and scales well for large sorts, too. Christian |
Andrew Z <formisc@gmail.com>: Jan 01 06:49PM -0800 On Wednesday, January 1, 2020 at 12:15:54 PM UTC-5, Manfred wrote: > On 1/1/2020 7:32 AM, Andrew Z wrote: > >>> OutletToggleTask is a non-static member function. ..... > This is not surprising, all of OutletToggleTask, OutletCallback and > GetCycleTicks are non-static member functions that are used invalidly, > although for different reasons. Oh, i see now. The outlet.GetCycleTicks is the pointer to the function, the outlet.GetCycleTicks() is the value of the function. thank you ery much! |
Robert Wessel <robertwessel2@yahoo.com>: Jan 01 06:26PM -0600 On Wed, 1 Jan 2020 23:21:23 +0100, David Brown >> Where's the support for the DEC PDP-11 and Honeywell 316 endianess??? >> ;-) >Gone - along with ones' complement integers. Are byte orders other than the two major ones actually disallowed now (or at least in C++20)? The enum provides at least a small loophole for non-big, non-little endian implorations. |
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jan 02 12:47AM >> Where's the support for the DEC PDP-11 and Honeywell 316 endianess??? >> ;-) > Gone - along with ones' complement integers. Not entirely! An implementation must signal a non-uniform endianness, but it can't, using std::endian alone, say much more about it. -- Ben. |
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