David Brown <david.brown@hesbynett.no>: Mar 26 11:58AM +0100 On 26/03/2020 09:30, Öö Tiib wrote: > level hardware drivers of hardware vendors and making it impossible > for smaller hardware vendors to write their drivers in anything but > assembler (that is rare and expensive skill these days). No, you are both misunderstanding this quite significantly. The re-ordering of the calculation in this code is allowed because the calculation of fibonacci(47) has no observable behaviour. Adding a memory fence around it will not force any order, because "result1" is not required to be in memory - though a compiler is certainly free to interpret the fence more generally and use it for ordering result1. Making result1 volatile /will/ force the desired order. Making the return type of functions like "time" volatile is just a silly idea. It makes no sense at all. Think about what volatile means, and it should be obvious. No version of C or C++ has a /carte blanche/ to remove infinite loops. Quoting from C11 (because I have it open at the moment): """ An iteration statement whose controlling expression is not a constant expression, 156) that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate. 157) """ In C++, this is part of the "forward progress guarantee", and amounts to the same thing. An infinite loop that does nothing is undefined behaviour - an infinite loop that does something observable is fine. And as for the suggested changes to "volatile", the recommendation is to disallow complicated cases and only allow simple ones. That is /fine/ - the complicated cases should never be used in the first place. So if you have: volatile int a, b, c; then a = 1; b = c; and the like are still allowed. You can have pointers-to-volatile, you can read and write volatile data, you can use pointer casts to make a "use a volatile access here" expressions (which every compiler has allowed, but was not defined behaviour until C18). What you can't do are things like: a = b++ + c++; That's fine. There is no standard for saying how these things should work, and compilers interpret then in very different ways. If your low-level drivers are affected by the new restrictions in volatile, then they /should/ be re-written - even if you are using older C++ standards. |
"Öö Tiib" <ootiib@hot.ee>: Mar 26 08:10AM -0700 On Thursday, 26 March 2020 12:32:29 UTC+2, David Brown wrote: > re-arrange that with respect to any side-effect code. There is a common > misunderstanding that code observable behaviour (or potentially having > observable behaviour) also forces an order on other code - it does not. I misunderstood that VS somehow reorders call to time() (that has to involve input or read of volatile) and cout output. |
"Öö Tiib" <ootiib@hot.ee>: Mar 26 08:13AM -0700 On Thursday, 26 March 2020 12:58:53 UTC+2, David Brown wrote: > memory fence around it will not force any order, because "result1" is > not required to be in memory - though a compiler is certainly free to > interpret the fence more generally and use it for ordering result1. That was already covered elsewhere in thread. > Making result1 volatile /will/ force the desired order. Unless they *deprecate* and *break* the volatile as they seemingly plan to. |
Ned Latham <nedlatham@woden.valhalla.oz>: Mar 26 12:27PM -0500 David Brown wrote: > Öö Tiib wrote: ----snip---- > The compiler can't re-order things with side-effects. But calculating > fibonacci() does not have any side-effects, and the compiler can > re-arrange that with respect to any side-effect code. Frankly, I can't see any reason whatever for reordering the programmer's code. If an optimiser sees an opportunity, it can suggest something, but it should be a suggestion only. > There is a common > misunderstanding that code observable behaviour (or potentially having > observable behaviour) also forces an order on other code - it does not. Code order should always be the programmer's province. |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Mar 26 08:26PM On Thu, 26 Mar 2020 11:40:27 +0100 > A smart enough compiler could see that fibonacci(47) can be > pre-calculated at compile time, and eliminate the run-time calculation > entirely. A less smart one might eliminate some of it, but not all. That makes sense. Thanks. I am not sure that that much freedom is a good idea though. |
David Brown <david.brown@hesbynett.no>: Mar 26 10:42PM +0100 On 26/03/2020 21:26, Chris Vine wrote: >> entirely. A less smart one might eliminate some of it, but not all. > That makes sense. Thanks. > I am not sure that that much freedom is a good idea though. Personally, I have no doubt that it is an excellent idea. It would be very difficult to specify rules that ban this case but allow other cases of re-arranging code and evaluations - and without the possibility of re-arrangement, you would cripple performance in many cases. (/You/ may have a super fast modern x86 cpu that does all sorts of hardware re-ordering of instructions, but not everyone does.) C and C++ have always had the "as if" rule and the concept of observable behaviour - and time is not observable. Any re-arrangements that don't affect the observable behaviour are allowed. |
David Brown <david.brown@hesbynett.no>: Mar 26 10:46PM +0100 On 26/03/2020 18:27, Ned Latham wrote: >> misunderstanding that code observable behaviour (or potentially having >> observable behaviour) also forces an order on other code - it does not. > Code order should always be the programmer's province. Only in assembly. C and C++ are high level languages. You say what you want, in terms of the language whose observable behaviour is defined for an abstract machine. The compiler can do whatever it wants to get object code that matches this behaviour. Intermediary steps between observable events (like passing output from the program, or calling an external function such as "time()") are irrelevant in the language, and the compiler can do whatever it wants there. A good compiler will usually do what it can to minimise the time this takes, but there may be other considerations (typically controlled by compiler flags) such as ease of debugging. The order of observable behaviour /is/ in the programmer's province. The process of calculating a pure function is not observable. |
David Brown <david.brown@hesbynett.no>: Mar 26 10:57PM +0100 On 26/03/2020 16:13, Öö Tiib wrote: > On Thursday, 26 March 2020 12:58:53 UTC+2, David Brown wrote: >> On 26/03/2020 09:30, Öö Tiib wrote: >>> On Thursday, 26 March 2020 05:36:57 UTC+2, Alf P. Steinbach wrote: <snip> >> Making result1 volatile /will/ force the desired order. > Unless they *deprecate* and *break* the volatile as they seemingly > plan to. Did you read the paper linked (P1152r4) ? """ The proposed deprecation preserves the useful parts of volatile, and removes the dubious / already broken ones. This paper aims at breaking at compile-time code which is today subtly broken at runtime or through a compiler update. The paper might also break another type of code: that which doesn't exist. This removes a significant foot-gun and removes unintuitive corner cases from the languages. """ Did you look at the votes? The solid majority of the working groups were in favour. Do you think they /all/ forgot that people use C++ in embedded programming? Can you give an example of a use of volatile that you think is good, solid programming practice in pre-C++20 but is not deprecated? At worst, you have to write "x = x + 1;" instead of "x++;". |
Christian Gollwitzer <auriocus@gmx.de>: Mar 26 07:44PM +0100 Am 26.03.20 um 08:53 schrieb Frederick Gotham: >> exclusively in English, especially if they ar ein the field of computer >> science (and most other fields, too). > Even if 99% of people don't bother having their paper translated into other languages, I shall. Your choice. I would still suggest that you first write the paper in English, and translate it afterwards only, as soon as it is finished. Then you can worry about the translation of the comments. In any case, you will need a proficient translator who is, in the ideal case, an expert in the field with their native tongue of the target language. Just some random translator will produce garbage. For some experience: I'm working in a scientific institute of the German government, we do have an internal translation and grammar checking service which does English and French, and we can request translations into other European and world languages which is realized by services from professional entrepreneur translators. I've used this sevice in the past for German->English and English->German translations, and for English language corrections. In all instances, they mistranslated/miscorrected some sentences because these people have studied languages, not physics - even if they know it better than most other translators, through experience in our institute. There are usually one or two iterations until both of us - the physics expert and the language expert - are happy. I can't imagine how this would work for a language which I do not understand, such as Arabic or Chinese. Unless you do speak these languages on an intermediate level, you'll need an expert friend with their mother tongue in the target language to crosscheck it. Christian |
Frederick Gotham <cauldwell.thomas@gmail.com>: Mar 26 12:51PM -0700 Christian wrote: > - the physics expert and the language expert - are happy. > I can't imagine how this would work for a language which > I do not understand, such as Arabic or Chinese. Thank you for this. It was a lot more clear cut in my head. Is there any translation firm which is held in particularly high regard for translating technical papers (e.g. to do with mathematics or computing). |
Frederick Gotham <cauldwell.thomas@gmail.com>: Mar 26 08:29AM -0700 The following code won't compile for me with GCC 7.4.0. Here's the output from the compiler: g++ -std=c++11 test.cpp -o prog test.cpp: In function 'int main()': test.cpp:80:7: error: no match for call to '(Transformer<Monkey>) (std::array<unsigned char, 16>&)' t(tmp); /* Why can't this find the method in the Base class? */ ^ test.cpp:49:7: note: candidate: void Transformer<T>::operator()(const std::array<unsigned char, 16>&, std::array<unsigned char, 16>&) const [with T = Monkey] void operator()(array<uint8_t,g_BLOCKSIZE> const &inBlock, array<uint8_t,g_BLOCKSIZE> &outBlock) const override ^~~~~~~~ test.cpp:49:7: note: candidate expects 2 arguments, 1 provided And here's the code: #include <cstddef> #include <cstdint> #include <array> #include <type_traits> using std::size_t; using std::uint8_t; using std::array; size_t constexpr g_BLOCKSIZE = 16u; class Transformer_Abstract { public: virtual ~Transformer_Abstract(void) {} /* Keep this virtual in case there's ever a container of pointers */ virtual void operator()(array<uint8_t,g_BLOCKSIZE> const &, array<uint8_t,g_BLOCKSIZE> &) const = 0; void operator()(array<uint8_t,g_BLOCKSIZE> &block) const { (*this)(block,block); } }; template<class T> class Transformer : public Transformer_Abstract { protected: bool const _is_forward; typename std::aligned_union<0,typename T::Encryption,typename T::Decryption>::type _storage; public: Transformer(bool const arg_is_forward) : _is_forward(arg_is_forward) { if ( _is_forward ) ::new(&_storage) typename T::Encryption(); else ::new(&_storage) typename T::Decryption(); } ~Transformer(void) override /* Base class should have a virtual destructor */ { if ( _is_forward ) reinterpret_cast<typename T::Encryption*>(&_storage)->T::Encryption::~Encryption(); else reinterpret_cast<typename T::Decryption*>(&_storage)->T::Decryption::~Decryption(); } void operator()(array<uint8_t,g_BLOCKSIZE> const &inBlock, array<uint8_t,g_BLOCKSIZE> &outBlock) const override { static uint8_t const nullblock[16] = {}; /* All zero */ if ( _is_forward ) reinterpret_cast<typename T::Encryption const *>(&_storage)->ProcessAndXorBlock(inBlock.begin(), nullblock, outBlock.begin()); else reinterpret_cast<typename T::Decryption const *>(&_storage)->ProcessAndXorBlock(inBlock.begin(), nullblock, outBlock.begin()); } }; void Pineapple(Transformer_Abstract &t) { array<uint8_t,g_BLOCKSIZE> tmp; t(tmp); /* This works fine */ } struct Monkey { struct Encryption { void ProcessAndXorBlock(uint8_t const *, uint8_t const *, uint8_t *) const {} }; struct Decryption { void ProcessAndXorBlock(uint8_t const *, uint8_t const *, uint8_t *) const {} }; }; auto main(void) -> int { Transformer<Monkey> t(true); Pineapple(t); array<uint8_t,g_BLOCKSIZE> tmp; t(tmp); /* Why can't this find the method in the Base class? */ } I thought that the method defined in the base class would be found and called? Do I need to use "using" here in the derived class? |
Paavo Helde <myfirstname@osa.pri.ee>: Mar 26 05:55PM +0200 On 26.03.2020 17:29, Frederick Gotham wrote: > I thought that the method defined in the base class would be found and called? Do I need to use "using" here in the derived class? Yep, the base class members are hidden by derived class members of the same name, you need this in the derived class public section: using Transformer_Abstract::operator(); There are also other problems in the code (mixing up iterators and pointers). |
"Öö Tiib" <ootiib@hot.ee>: Mar 26 08:48AM -0700 On Thursday, 26 March 2020 17:30:14 UTC+2, Frederick Gotham wrote: > t(tmp); /* Why can't this find the method in the Base class? */ > } > I thought that the method defined in the base class would be found and called? Do I need to use "using" here in the derived class? Yes. Or to make all overloads in base class virtual. Otherwise hiding takes place. The keywords like strict and hiding were proposed into C++11 to make compiler to lament about that common confusion but were not accepted. That bear trap into what everyone must fall is there because C++ is designed to *hate* novices. |
Frederick Gotham <cauldwell.thomas@gmail.com>: Mar 26 09:19AM -0700 Paavo wrote: > There are also other problems in the > code (mixing up iterators and pointers). You don't like how I use the return value from "array::begin(void)" as a pointer to the first element? |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 26 06:17PM +0100 On 26.03.2020 17:19, Frederick Gotham wrote: >> code (mixing up iterators and pointers). > You don't like how I use the return value from "array::begin(void)" > as a pointer to the first element? It's not necessarily a pointer. You can convert to pointer by putting `&*` in front. But I fail to understand the purpose of the low level shenanigans here. I would guess that things would be much simpler with `std::vector`. - Alf |
Paavo Helde <myfirstname@osa.pri.ee>: Mar 26 07:18PM +0200 On 26.03.2020 18:19, Frederick Gotham wrote: >> There are also other problems in the >> code (mixing up iterators and pointers). > You don't like how I use the return value from "array::begin(void)" as a pointer to the first element? Not me - it's the compiler! 1> ] 1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(55): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called 1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(51): note: while compiling class template member function 'void Transformer<Monkey>::operator ()(const std::array<uint8_t,16> &,std::array<uint8_t,16> &) const' 1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(75): note: see reference to class template instantiation 'Transformer<Monkey>' being compiled 1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(57): error C2664: 'void Monkey::Decryption::ProcessAndXorBlock(const uint8_t *,const uint8_t *,uint8_t *) const': cannot convert argument 1 from 'std::_Array_const_iterator<_Ty,16>' to 'const uint8_t *' 1> with 1> [ 1> _Ty=uint8_t 1> ] 1>d:\test\consoletestvs2017\consoletestvs2017\main.cpp(57): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called |
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