- CHAR_BIT is not eight - 7 Updates
- I will cut off cross-posting - 1 Update
- MIT Professor Michael Sipser validates the notion of a simulating halt decider V2 - 3 Updates
- static array of reference_wrapper - 8 Updates
- Is there any UB lurking around in here? - 6 Updates
| Bonita Montero <Bonita.Montero@gmail.com>: Oct 16 07:51AM +0200 Am 15.10.2022 um 21:03 schrieb Mr Flibble: >> with the containers that have random access iterators. > No. Obviously rebinding from T to a list node containing T can work > with a custom allocator. I didn't say anything different. |
| David Brown <david.brown@hesbynett.no>: Oct 16 05:03PM +0200 On 15/10/2022 13:45, Mr Flibble wrote: >> code or data space, however - though it does happen.) > Try using std::list with a custom allocator as I originally suggested; > also your quote of 7KB sounds highly dubious and anecdotal. Of course the example of 7 KB is anecdotal - I told you I made a quick test. It doesn't get more anecdotal than that. But no, it is not "highly dubious" - it is really what I got. Every programmer works in a particular area, or small set of areas - /nobody/ has experience and knowledge of all kinds of programming. The trick to having realistic conversations and not appearing arrogant and ignorant is to understand your limitations. You simply don't know what you are talking about when it comes to small-systems embedded programming, and some of the challenges or limitations involved that are different from the kind of programming you are used to. (And similarly there is plenty about the kind of coding /you/ do that I am ignorant about.) So it is /fine/ for you to ask "why don't you just use a std::list with a custom allocator". It is /not/ fine for you to claim people are wrong when they tell you why they don't do that. Why don't I write a custom allocator for std::list and then use that instead of the pointer-based "home made" linked list I have now? I don't do so because it is a lot of effort and will result in bigger, slower, wasteful and vastly more complicated code than the two dozen or so lines of shared C and C++ code I have at the moment that has worked fine for the last 20+ years. It's not unlikely that with a custom allocator and disabled exceptions I could probably get the overhead of std::list down to 2 or 3 KB rather than 7 KB. But that only makes it not quite as inefficient - it still is not close to the efficiency and convenience of the custom solution. And that would come after writing far more code to make the "standard" container work than it took to make a completely custom solution. |
| Mr Flibble <flibble@reddwarf.jmc.corp>: Oct 16 04:34PM +0100 On Sun, 16 Oct 2022 17:03:38 +0200 > efficiency and convenience of the custom solution. And that would > come after writing far more code to make the "standard" container > work than it took to make a completely custom solution. So you admit that you *might* be able to get it down to 2KB; so I was correct in my analysis and it is you who is arrogant not me. I am also well aware of the constraints involved in embedded programming and your assumption that I am not is another sign of your arrogance. It is highly unlikely that your solution is more performant than std::list; a double linked list is hardly rocket science and standard library implementations are generally written by people who know what they are doing. So you can either apologize or fuck off. /Flibble |
| David Brown <david.brown@hesbynett.no>: Oct 16 06:51PM +0200 On 16/10/2022 17:34, Mr Flibble wrote: >> work than it took to make a completely custom solution. > So you admit that you *might* be able to get it down to 2KB; so I was > correct in my analysis and it is you who is arrogant not me. Sorry, you seem to be having trouble understanding the conversation. No, your analysis was not correct - the 7 KB was not "highly dubious", but an actual measurement on real code that was compiled and linked (with a case sample size of 1). Disabling exceptions would have been simple, and it is common practice on small embedded systems - just as avoiding most standard library containers (and much of the C and C++ standard libraries) is common practice on small embedded systems. Leaving exceptions enabled is a fairer test, however, as it would be realistic for the kind of programmer who thinks std::list<> and custom allocators is a good idea for the task in hand. > I am also > well aware of the constraints involved in embedded programming and your > assumption that I am not is another sign of your arrogance. I can only assume based on what you write - and you do not write as someone who has experience in small-systems embedded programming. > std::list; a double linked list is hardly rocket science and standard > library implementations are generally written by people who know what > they are doing. It would not surprise me if my solution is an order of magnitude better performing than std::list<>. (Not that I claim the difference would be significant for the use in question. std::list<> is going to be pretty efficient, but a very simple custom single linked list can be considerably more efficient.) As you say, a linked list is not rocket science - there's no need for custom allocators and standard library containers when all that's needed is a "pointer to next node" field in the node structure. > So you can either apologize or fuck off. You are joking, yes? You think I should apologize for your misunderstandings, your unwarranted assumptions, your accusations of dishonesty and your belief that you know better than anyone else about fields of programming that are completely beyond your experience? I'm will try to avoid posting more in this subthread unless it contributes something positive. Hopefully you'll do the same. |
| David Brown <david.brown@hesbynett.no>: Oct 16 07:10PM +0200 On 16/10/2022 00:42, Frederick Virchanza Gotham wrote: >> Did you actually write the cipher? Or did you get the code from GitHub? > I can't find an algorithm that will fit on the microcontroller so I'm writing my own. > 99% of the program memory is already taken up. This was for an Arduino, using an 8-bit AVR ? Have you much experience with the device? And are you using the Arduino toolchain and IDE, or a plain avr-gcc build? The Arduino toolchain can make it difficult to optimise well - you have limited control of the build flags. And the Ardunio libraries are designed for ease of use for beginners, not efficiency. (At least, this was all the case last time I tried it.) In general for the AVR, make sure you use uint8_t types whenever possible, as they are much more efficient than "int". Avoid pointers, and use statically allocated data as much as you can. Make sure you have "-fno-rtti -fno-exceptions". Check the generated assembly code - the AVR backend is underfunded and understaffed, so though the people who have worked on it have done a fantastic job, there are many "missed optimisation opportunity" issues and missing peephole optimisations. That means that sometimes small changes to the source code with no real semantic differences can sometimes lead to significant object code changes. Fancy branchless expressions or heavy use of tertiary operators that give efficient results on an x86 could end up much worse results than simple branched code. Avoid divisions, and avoid any floating point. Remember that on this kind of device, even shift operators are slow (especially for anything bigger than 8-bit). Much the same applies to the TMS320 (except you want uint16_t, not uint8_t !). But be wary of trying to read the generated TMS320 assembly code. AVR assembly is easy to understand - TMS320 assembly will drive you insane. |
| Mr Flibble <flibble@reddwarf.jmc.corp>: Oct 16 06:11PM +0100 On Sun, 16 Oct 2022 18:51:56 +0200 > experience? > I'm will try to avoid posting more in this subthread unless it > contributes something positive. Hopefully you'll do the same. You continue to prove that you are an arrogant ass who is clueless as far as writing performant code is concerned. Fuck off. /Flibble |
| Mr Flibble <flibble@reddwarf.jmc.corp>: Oct 16 07:18PM +0100 On Sun, 16 Oct 2022 18:51:56 +0200 > experience? > I'm will try to avoid posting more in this subthread unless it > contributes something positive. Hopefully you'll do the same. I know Fedora isn't an embedded target but I was interested to see what the difference using std::list makes to elf binary size (symbols stripped): int main() { } [leigh@fedora ~]$ g++ foo.cpp [leigh@fedora ~]$ strip a.out [leigh@fedora ~]$ ls -l a.out -rwxr-xr-x 1 leigh leigh 14952 Oct 16 19:09 a.out #include <list> int main() { std::list<int> l; l.push_back(42); } [leigh@fedora ~]$ g++ foo.cpp [leigh@fedora ~]$ strip a.out [leigh@fedora ~]$ ls -l a.out -rwxr-xr-x 1 leigh leigh 15192 Oct 16 19:10 a.out [leigh@fedora ~]$ g++ -fno-exceptions foo.cpp [leigh@fedora ~]$ strip a.out [leigh@fedora ~]$ ls -l a.out -rwxr-xr-x 1 leigh leigh 15088 Oct 16 19:10 a.out So that is just 240 extra bytes to binary file size when using std::list ctor, dtor and push_back; and even less bytes if we disable exceptions. Again, feel free to apologize or fuck off; and don't assume I don't know what I am talking about again; it is just civilised and basic good manners to assume the person opposite isn't a dumb fuck. /Flibble |
| Bonita Montero <Bonita.Montero@gmail.com>: Oct 16 06:18PM +0200 Am 16.10.2022 um 17:57 schrieb olcott: > This time when I cross-posted I left comp.lang.c off the list because I > can see how my cross-posts have overwhelmed comp.lang.c. > I will cut off Flibble's cross-posting much sooner in the future. I was talking about your motivation and not about your formalities. You're really obsessed ! |
| olcott <polcott2@gmail.com>: Oct 16 10:16AM -0500 <Sipser approved abstract> MIT Professor Michael Sipser has agreed that the following verbatim paragraph is correct (he has not agreed to anything else in this paper): If simulating halt decider H correctly simulates its input D until H correctly determines that its simulated D would never stop running unless aborted then H can abort its simulation of D and correctly report that D specifies a non-halting sequence of configurations. </Sipser approved abstract> to this paper: *Rebutting the Sipser Halting Problem Proof* https://www.researchgate.net/publication/364302709_Rebutting_the_Sipser_Halting_Problem_Proof The proof that the simulation of D by H is correct and that this correctly simulated D would never stop running unless aborted is on page 3 of the above paper. People that fail to comprehend the technical details of page 3 are unqualified to assess the correctness of page 3. The technical prerequisites for page 3 are expert knowledge of the C programming language, knowledge of x86 assembly language and how the C calling conventions are implemented in x86 assembly language. Page 4 shows the application of a simulating halt decider to the Peter Linz proof proving that the "impossible" input ⟨Ĥ⟩ ⟨Ĥ⟩ to the embedded copy of Linz H contained within Linz Ĥ is correctly construed as specifying non-halting sequence of configurations. -- Copyright 2022 Pete Olcott "Talent hits a target no one else can hit; Genius hits a target no one else can see." Arthur Schopenhauer |
| Mr Flibble <flibble@reddwarf.jmc.corp>: Oct 16 04:37PM +0100 On Sun, 16 Oct 2022 10:16:48 -0500 > Peter Linz proof proving that the "impossible" input ⟨Ĥ⟩ ⟨Ĥ⟩ to the > embedded copy of Linz H contained within Linz Ĥ is correctly > construed as specifying non-halting sequence of configurations. You have been told multiple times now that you are not doing a correct simulation of D so it doesn't matter what Sipser says. The correct simulation of D by H is D behaving as if there was a direction execution of D(D). /Flibble |
| olcott <none-ya@beez-waxes.com>: Oct 16 10:44AM -0500 On 10/16/2022 10:37 AM, Mr Flibble wrote: >> construed as specifying non-halting sequence of configurations. > You have been told multiple times now that you are not doing a correct > simulation of D By people not having the technical competence (see above technical prerequisites) to verify that this simulation is correct. -- Copyright 2022 Pete Olcott "Talent hits a target no one else can hit; Genius hits a target no one else can see." Arthur Schopenhauer |
| "daniel...@gmail.com" <danielaparker@gmail.com>: Oct 15 05:37PM -0700 On Saturday, October 15, 2022 at 6:42:27 PM UTC-4, Marcel Mueller wrote: > }; > conversion from 'ColumnRenderer' to non-scalar type > 'std::reference_wrapper<const ColumnRenderer>' requested I would understand your example better if it were written as ColumnRenderer renderer1; ColumnRenderer renderer2; static const std::reference_wrapper<const ColumnRenderer> Renderers[] = { renderer1, renderer2 }; (which I'm sure compiles.) But what is the point of initializing it with ColumnRenderer() ... ColumnRenderer()? I don't believe std::reference_wrapper has a constructor that would allow an implicit conversion from those, see https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/reference_wrapper Daniel |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 09:00PM -0700 On 10/15/2022 3:42 PM, Marcel Mueller wrote: > Why? I thought reference_wrapper is intended to be used with arrays. > Or is this one of the blemishes of C++11 that has been fixed in later > versions? `std::reference_wrapper<>` is not a reference. It will not extend the lifetime of temporaries the same way a true reference does. How did you expect your code to work? To prevent you from making such erroneous assumptions and running into subsequent problems, the class specification has a dedicated requirement (see https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/reference_wrapper): --- template< class U > constexpr reference_wrapper( U&& x ) noexcept(/*see below*/) ; Converts x to T& as if by T& t = std::forward<U>(x), then stores a reference to t. This overload participates in overload resolution only if typename std::decay<U>::type is not the same type as reference_wrapper and the expression FUN(std::declval<U>()) is well-formed, where FUN names the set of imaginary functions void FUN(T&) noexcept; void FUN(T&&) = delete; --- That `FUN` part is the one intended to reject binding to non-lvalues. Which is exactly what happens in your case. > constexpr reference(T& ref) : Ref(ref) { } > constexpr operator T&() const { return Ref; } > }; No, it doesn't. It merely "compiles". But the temporaries get destroyed almost immediately and you end up with a bunch of dangling references. -- Best regards, Andrey |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 09:09PM -0700 On 10/15/2022 9:00 PM, Andrey Tarasevich wrote: > --- > That `FUN` part is the one intended to reject binding to non-lvalues. > Which is exactly what happens in your case. Hm... Looks like my explanation is not entirely accurate. The argument of `FUN` is supposed to be `std::declval<U>()`, which should pass the test in this case. It does look like the standard constructor is rejecting your temporaries. And it is true that you would end up with dangling references if it accepted them. But the explanation of the underlying mechanism that I provided is probably inaccurate. -- Best regards, Andrey |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 09:30PM -0700 On 10/15/2022 9:09 PM, Andrey Tarasevich wrote: > temporaries. And it is true that you would end up with dangling > references if it accepted them. But the explanation of the underlying > mechanism that I provided is probably inaccurate. No, everything is fine with my explanation. This trick is based on how universal references, reference-collapsing rules and `std::declval<>` interact with each other. When you pass a non-lvalue to the constructor of `std::reference_wrapper`, type `U` is deduced as a plain (non-reference) type (`ColumnRenderer ` is your case). Then `std::declval<ColumnRenderer>` produces a `ColumnRenderer> &&` result. This result is an xvalue, which cannot serve as an argument for `FUN(T &)`. Compilation fails. This is why the constructor rejects non-lvalue arguments. When you pass an lvalue to the constructor of `std::reference_wrapper`, type `U` is deduced as an lvalue reference type. Then `std::declval<>` produces an lvalue reference result. That result can serve as an argument for `FUN(T &)`, which is why the constructor accepts lvalues. -- Best regards, Andrey |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 09:36PM -0700 > ColumnRenderer() ... ColumnRenderer()? I don't believe std::reference_wrapper > has a constructor that would allow an implicit conversion from those, see > https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/reference_wrapper Fwiw: ______________________________ #include <iostream> #include <functional> struct render { int m_foo; }; static render g_farm_concrete[] = { { 0 }, { 1 }, { 2 } }; static const std::reference_wrapper<const render> g_farm_refs[] = { g_farm_concrete[0], g_farm_concrete[1], g_farm_concrete[2] }; int main() { std::cout << "g_farm_concrete[0]" << &g_farm_concrete[0] << "\n"; std::cout << "g_farm_concrete[1]" << &g_farm_concrete[1] << "\n"; std::cout << "g_farm_concrete[2]" << &g_farm_concrete[2] << "\n"; std::cout << "\n"; std::cout << "g_farm_refs[0]" << &g_farm_concrete[0].m_foo << "\n"; std::cout << "g_farm_refs[1]" << &g_farm_concrete[1].m_foo << "\n"; std::cout << "g_farm_refs[2]" << &g_farm_concrete[2].m_foo << "\n"; return 0; } ______________________________ Output: g_farm_concrete[0]0x5616e1d98010 g_farm_concrete[1]0x5616e1d98014 g_farm_concrete[2]0x5616e1d98018 g_farm_refs[0]0x5616e1d98010 g_farm_refs[0]0x5616e1d98014 g_farm_refs[0]0x5616e1d98018 |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 09:41PM -0700 On 10/15/2022 9:36 PM, Chris M. Thomasson wrote: > g_farm_refs[0]0x5616e1d98010 > g_farm_refs[0]0x5616e1d98014 > g_farm_refs[0]0x5616e1d98018 God damn it! I accidentally posted the old output when I realized I messed up the index for g_farm_refs[0], I forgot the [1] and[2]: corrected: g_farm_concrete[0]0x563ec9835010 g_farm_concrete[1]0x563ec9835014 g_farm_concrete[2]0x563ec9835018 g_farm_refs[0]0x563ec9835010 g_farm_refs[1]0x563ec9835014 g_farm_refs[2]0x563ec9835018 Sorry about that nonsense. Fwiw, the pointers are going to the same locations, but this still seems a little bit, sort of, "odd" to me wrt an array of constant references to the g_farm_concrete array. |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 09:45PM -0700 On 10/15/2022 9:41 PM, Chris M. Thomasson wrote: > On 10/15/2022 9:36 PM, Chris M. Thomasson wrote: >> On 10/15/2022 5:37 PM, daniel...@gmail.com wrote: >>> On Saturday, October 15, 2022 at 6:42:27 PM UTC-4, Marcel Mueller wrote: [... > Sorry about that nonsense. Fwiw, the pointers are going to the same > locations, but this still seems a little bit, sort of, "odd" to me wrt > an array of constant references to the g_farm_concrete array. Damn bugs I forgot to actually use the g_farm_refs. I should create a new post: _________________________________ #include <iostream> #include <functional> struct render { int m_foo; }; static render g_farm_concrete[] = { { 0 }, { 1 }, { 2 } }; static const std::reference_wrapper<const render> g_farm_refs[] = { g_farm_concrete[0], g_farm_concrete[1], g_farm_concrete[2] }; int main() { std::cout << "g_farm_concrete[0]" << &g_farm_concrete[0] << "\n"; std::cout << "g_farm_concrete[1]" << &g_farm_concrete[1] << "\n"; std::cout << "g_farm_concrete[2]" << &g_farm_concrete[2] << "\n"; std::cout << "\n"; std::cout << "g_farm_refs[0]" << &g_farm_refs[0].get().m_foo << "\n"; std::cout << "g_farm_refs[1]" << &g_farm_refs[1].get().m_foo << "\n"; std::cout << "g_farm_refs[2]" << &g_farm_refs[2].get().m_foo << "\n"; return 0; } _________________________________ |
| Marcel Mueller <news.5.maazl@spamgourmet.org>: Oct 16 10:00AM +0200 Am 16.10.22 um 06:00 schrieb Andrey Tarasevich: >> }; > No, it doesn't. It merely "compiles". But the temporaries get destroyed > almost immediately and you end up with a bunch of dangling references. You are right. The constructor call will use a temporary. The helper need to be changed to: template <typename T> struct reference { T& Ref; constexpr operator T&() const { return Ref; } }; In this case it is a struct initialization rather than a constructor which will extend the lifetime. I have seen this in an old project and tried to migrate it to std::reference_wrapper which is not possible. Marcel |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 09:47PM -0700 Is this code okay, or busted in some way? In reference to the following thread: (static array of reference_wrapper) https://groups.google.com/g/comp.lang.c++/c/_RszdtnypkE Well, what horrors lie below? ;^) ______________________________ #include <iostream> #include <functional> struct render { int m_foo; }; static render g_farm_concrete[] = { { 0 }, { 1 }, { 2 } }; static const std::reference_wrapper<const render> g_farm_refs[] = { g_farm_concrete[0], g_farm_concrete[1], g_farm_concrete[2] }; int main() { std::cout << "g_farm_concrete[0]" << &g_farm_concrete[0] << "\n"; std::cout << "g_farm_concrete[1]" << &g_farm_concrete[1] << "\n"; std::cout << "g_farm_concrete[2]" << &g_farm_concrete[2] << "\n"; std::cout << "\n"; std::cout << "g_farm_refs[0]" << &g_farm_refs[0].get().m_foo << "\n"; std::cout << "g_farm_refs[1]" << &g_farm_refs[1].get().m_foo << "\n"; std::cout << "g_farm_refs[2]" << &g_farm_refs[2].get().m_foo << "\n"; return 0; } ______________________________ I get: g_farm_concrete[0]0x562b8e2d9010 g_farm_concrete[1]0x562b8e2d9014 g_farm_concrete[2]0x562b8e2d9018 g_farm_refs[0]0x562b8e2d9010 g_farm_refs[1]0x562b8e2d9014 g_farm_refs[2]0x562b8e2d9018 Just lucky? |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 10:53PM -0700 On 10/15/2022 9:47 PM, Chris M. Thomasson wrote: > (static array of reference_wrapper) > https://groups.google.com/g/comp.lang.c++/c/_RszdtnypkE > Well, what horrors lie below? ;^) Why would there be? I don't see any potential for any problems there. -- Best regards, Andrey |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 11:00PM -0700 On 10/15/2022 10:53 PM, Andrey Tarasevich wrote: >> https://groups.google.com/g/comp.lang.c++/c/_RszdtnypkE >> Well, what horrors lie below? ;^) > Why would there be? I don't see any potential for any problems there. Needing to use indirection wrt not being able to have a raw array of references. ________________________ #include <iostream> struct foo { int m_a; }; static foo g_foo[] = { { 0 }, { 1 } }; static foo& g_foo_ref[] = { g_foo[0], g_foo[1] }; int main() { return 0; } ________________________ No compile for you! Common Man... ;^) |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 11:05PM -0700 On 10/15/2022 11:00 PM, Chris M. Thomasson wrote: >> Why would there be? I don't see any potential for any problems there. > Needing to use indirection wrt not being able to have a raw array of > references. But that's what `std::reference_wrapper<>` is for. -- Best regards, Andrey |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 15 11:50PM -0700 On 10/15/2022 11:05 PM, Andrey Tarasevich wrote: >> Needing to use indirection wrt not being able to have a raw array of >> references. > But that's what `std::reference_wrapper<>` is for. It works for sure. However, it seems like: static foo g_foo[] = { { 0 }, { 1 } }; static foo& g_foo_ref[] = { g_foo[0], g_foo[1] }; should work as well, but it does not. I forgot the reason why. |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 15 11:56PM -0700 On 10/15/2022 11:50 PM, Chris M. Thomasson wrote: > static foo g_foo[] = { { 0 }, { 1 } }; > static foo& g_foo_ref[] = { g_foo[0], g_foo[1] }; > should work as well, but it does not. I forgot the reason why. The reason for "there shall be no no arrays of references"? Probably because it would open a lot of unpleasant cans of worms. Reference is not an object type in C++. It is unspecified whether it occupies storage. This does not play well with arrays, which require types of definitive size, which support address arithmetic. -- Best regards, Andrey |
| 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