- what do people use for automated testing of C++ Windows app ? - 10 Updates
- Using std::vec "push_back" on a vector of objects which contain unique_ptrs - 2 Updates
- #include "..." - 4 Updates
- #include "..." - 2 Updates
- Why c++ executes destructors of moved objects? - 2 Updates
- Convert char to int - 3 Updates
- Backporting std::move code - 1 Update
- Using a lookup table at compile time - 1 Update
Lynn McGuire <lynnmcguire5@gmail.com>: Aug 23 06:52PM -0500 On 8/20/2016 5:20 PM, Lynn McGuire wrote: > http://stackoverflow.com/questions/1287425/automated-testing-for-c-c-gui-applications > Thanks, > Lynn We have decided to add more application specific tests for now that we run from the command line. Thanks, Lynn |
"Öö Tiib" <ootiib@hot.ee>: Aug 24 01:42AM -0700 On Tuesday, 23 August 2016 10:00:00 UTC+3, David Brown wrote: > /None/ of them pay an appropriate level of tax in the countries where > they make they money. So while I fully agree that Google is bad at > this, it is no worse than the other big IT companies. I had different impression but I'm no expert to judge it myself. So may be there are only putrid apples. ;) > exceptions, but don't really understand all the details needed to make > properly exception-safe code, or who treat exceptions as just a way of > giving the user an error message when something goes wrong. Only some pre-standard versions of C++ did not have exceptions and so it is not good tool for people who can't handle those. Also C++ is sort of tricky for those who do not follow RAII. There are some programming languages (unfortunately very few) that lack exceptions so perhaps such people should use one of those languages. Existence of such people is not good reason to forbid exceptions. |
David Brown <david.brown@hesbynett.no>: Aug 24 01:14PM +0200 On 24/08/16 10:42, Öö Tiib wrote: >> this, it is no worse than the other big IT companies. > I had different impression but I'm no expert to judge it myself. So may be > there are only putrid apples. ;) I am not an expert myself. It could be that Google is worse than others - the real point is that they are /all/ bad. And of course, how "bad" they are can depend on your viewpoints. Is a company that dodges taxes but gives other things to the community "bad"? Is it "bad" if it provides cheap services to customers but uses bullying (legal or not) tactics on competitors? Should a company pay taxes in its "mother" country, or in different countries based on where it gets its income, or different countries based on where it makes a profit, or in countries based on where it has employees? Once you realise that they are all bad in some way, you don't have to feel guilty about using their services! > programming languages (unfortunately very few) that lack exceptions > so perhaps such people should use one of those languages. Existence > of such people is not good reason to forbid exceptions. /If/ you are in a position to use exceptions well, then there are advantages in using them. But that means that /you/, and all the other programmers on your team, need to understand them and use them appropriately. It also means that any libraries or third-party code you use must be equally good. And since "exception safe" can mean many different things ("basic" guarantee, "strong" guarantee, "nothrow" guarantee) you have to make sure you have everything coordinated appropriately. RAII is necessary for making code exception-safe. But it is not sufficient, and you certainly don't need exceptions in order to make good use of RAII. The facts are that writing /really/ exception-safe code is often hard (though modern features such as unique_ptr makes it a good deal easier), and can often lead to verbose or inefficient code. You can quickly find that you need to make extra little classes and put code in the constructor and destructor (again, unique_ptr can simplify this a lot). It is easy to write code that looks safe, but has hidden flaws, as it can be hard to know where exceptions might be thrown. People often claim that exception handling is free - noting that with stack unwind tables, code that uses exceptions typically runs faster than similar code that has explicit checking for failures. While that is true as far as it goes, it is far from always the case, for a variety of reasons. One is that on some targets, it is not as efficient - and the cost of the space needed for the tables can be significant (think small embedded systems). Another is that it can hinder optimisations (by enforcing ordering of operations, or pushing local objects onto the stack). And if you are trying to get a "strong" exception safe guarantee, you often need a good deal more code, and a good deal slower code. A function that modifies an object "x" with the strong guarantee will typically take a copy "x2" of "x", modify "x2" in a way that might thrown an exception, and then swap "x" and "x2" once everything is completed safely. That means an extra copy-constructor, and an extra destructor - that's hardly free if "x" is a large data structure. There are, of course, a great many benefits to be had from using exceptions and writing exception-safe code. But you need to be clear that the benefits only come if the code really is exception safe, that it is realistic for exceptions to occur, and that you have something useful that you can do /if/ an exception occurs. C++ gives you the /option/ of using exceptions - it does not force you to do so, and it is not always the right choice. |
Jerry Stuckle <jstucklex@attglobal.net>: Aug 24 11:48AM -0400 On 8/24/2016 4:42 AM, Öö Tiib wrote: > programming languages (unfortunately very few) that lack exceptions > so perhaps such people should use one of those languages. Existence > of such people is not good reason to forbid exceptions. In this case I agree completely. Exceptions have their place, and good C++ programmers know how to use them properly. But all too often I've seen them misused. A good example would be throwing an exception for a "NOT FOUND" response from a database query. That is a normal response which should be expected, and should be handled appropriately. Exceptions should be used for abnormal responses and similar unexpected conditions such as "ABORTED CONNECTION". -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
legalize+jeeves@mail.xmission.com (Richard): Aug 24 04:30PM [Please do not mail me a copy of your followup] Lynn McGuire <lynnmcguire5@gmail.com> spake the secret code >We have decided to add more application specific tests for now that we >run from the command line. So if I understand you correctly: - your application can accept inputs from the command-line and write out results to a file - your application tests invoke the tool from the command-line and verify the resulting file(s) This is a very reasonable way to write acceptance tests and/or regression tests. FitNesse can be useful in this scenario as well. The command-line arguments are documented on the FitNesse wiki page describing the test and the expected file contents are also described on the same wiki page. You glue them to your application by writing a FitNesse fixture or using an existing fixture. Once your fixture builds up enough custom verification primitives, you find that you cna express new tests as new FitNesse wiki pages without having to write more code. The idea behind FitNesse originally was to create a way for the business analysts and product owners to create acceptance criteria in a way that not only made sense to them but also became an executable unit that could directly verify the functionality. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Aug 24 05:44PM +0100 On 24/08/2016 16:48, Jerry Stuckle wrote: > That is a normal response which should be expected, and should be > handled appropriately. Exceptions should be used for abnormal responses > and similar unexpected conditions such as "ABORTED CONNECTION". Exceptions can be used for expected conditions too and I would argue "ABORTED CONNECTION" is probably one such expected condition; invalid user input is another. /Flibble |
Jerry Stuckle <jstucklex@attglobal.net>: Aug 24 12:53PM -0400 On 8/24/2016 12:44 PM, Mr Flibble wrote: > "ABORTED CONNECTION" is probably one such expected condition; invalid > user input is another. > /Flibble You would. But GOOD C++ programmers know better. And no, "ABORTED CONNECTION" would not be a condition that would normally occur, and would not be expected. At least not in any decent system. Maybe it is on the ones you work with. And invalid user input is an expected condition and should be handled appropriately - not with exceptions. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Aug 24 06:05PM +0100 On 24/08/2016 17:53, Jerry Stuckle wrote: > system. Maybe it is on the ones you work with. > And invalid user input is an expected condition and should be handled > appropriately - not with exceptions. Your fractal wrongness continues unabated it seems. Exceptions are not just for *fatal* errors; if that were the cause there would be little point having the ability to catch exceptions. Exceptions are also useful for handling non-fatal, i.e. recoverable, conditions without having to resort to the old fashioned C-way of returning error codes manually up the call stack to indicate an error. It is obvious given your outlook that you do not know how to design software properly through the use of layered abstractions through which exceptions are an ideal way for transmitting errors of all kinds. /Flibble |
"Öö Tiib" <ootiib@hot.ee>: Aug 24 10:35AM -0700 On Wednesday, 24 August 2016 14:14:15 UTC+3, David Brown wrote: > programmers on your team, need to understand them and use them > appropriately. It also means that any libraries or third-party code you > use must be equally good. So part of exception handling skill is how *not* to throw into legacy code (module or library) that expects nothrow but does not constrain it in interface or how to edit the interface to constrain it. About unskilled people it is anyway gamble. Can't handle exceptions? Can they manage resources? Resources besides memory? Can they handle threads and locks? Etc. C++ without exceptions is no way simple and foolproof tool. > different things ("basic" guarantee, "strong" guarantee, "nothrow" > guarantee) you have to make sure you have everything coordinated > appropriately. These guarantees are trivial and obvious. Let me list? * The "nothrow" guarantee is marked with "noexcept" specifier in C++. Exceptions won't be ever thrown out of such functions. How it can be simpler? * "Basic" guarantee is that all objects will be in valid invariant and there are no resource leaks when exception is thrown out of function. That very guarantee is expected *always* in C++ regardless if function does throw or not. So it is only essential and is achievable with RAII alone on case of exceptions. * "Strong" guarantee means that function rolls everything back into state before call if it throws. That means special design effort is used that can be expensive. That design effort however does not differ from a function that has no side effects (rolls everything back) when it returns an error code. So it is special *functionality* and is expected to be documented about a function. > RAII is necessary for making code exception-safe. But it is not > sufficient, and you certainly don't need exceptions in order to make > good use of RAII. RAII is sufficient for achieving basic guarantee. It does not achieve roll-back guarantee automatically on general case, but nothing does that. RAII is essential for other reasons anyway, exactly my point. > constructor and destructor (again, unique_ptr can simplify this a lot). > It is easy to write code that looks safe, but has hidden flaws, as it > can be hard to know where exceptions might be thrown. The 'unique_ptr' has been around for years. Before it there was a decade when 'boost::scoped_ptr' was available. Efficiency-wise it is about as good, it just does essential things. Before that there was time when C++ wasn't standardized and both templates and exceptions were sort of expensively and inconsistently implemented so I avoided those. That was two decades ago however. > than similar code that has explicit checking for failures. While that > is true as far as it goes, it is far from always the case, for a variety > of reasons. Not free but often cheaper and that is why it is often faster. > One is that on some targets, it is not as efficient - and > the cost of the space needed for the tables can be significant (think > small embedded systems). Very small embedded systems and bad quality of some implementations are red herrings again. Small systems do trivial things and so usage of most features of C++ (including exceptions) are likely overengineering there. Usage of low quality tools can result with unanticipated expenses regardless if we use exceptions or not. It is same as with unskilled workforce, exceptions are not *the* issue there and don't stand out as special, something else is the issue. > thrown an exception, and then swap "x" and "x2" once everything is > completed safely. That means an extra copy-constructor, and an extra > destructor - that's hardly free if "x" is a large data structure. What you mean? We often have to make backup copies of objects when failed attempt of operation may change it (but we guarantee not to) regardless if we throw exception after we failed or we return error code. What else you suggest to do on general case? > useful that you can do /if/ an exception occurs. C++ gives you the > /option/ of using exceptions - it does not force you to do so, and it is > not always the right choice. With that I agree. Also I feel that I have never claimed that usage of exceptions is correct choice in every situation. Exceptions are good only for to handle exceptional situations (like name indicates). That does not mean that such handling itself is rare in code. In mature program over half of handled situations are exceptional. |
Jerry Stuckle <jstucklex@attglobal.net>: Aug 24 04:00PM -0400 On 8/24/2016 1:05 PM, Mr Flibble wrote: > software properly through the use of layered abstractions through which > exceptions are an ideal way for transmitting errors of all kinds. > /Flibble I didn't say anything about *fatal* errors. That's YOUR WORDS. And no, GOOD programmers know exceptions are NOT an "ideal way for transmitting errors of all kinds". Among other things, the overhead of exception handling is quite high. And exceptions never were designed to handle "all kinds of errors". Good programmers know how to use exceptions effectively. Crappy programmers misuse them for all kinds of things they weren't meant for. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
bitrex <bitrex@de.lete.earthlink.net>: Aug 24 03:28PM -0400 Having a bit of trouble with code like this (still getting acquainted with 21st century C++): #include <vector> #include <memory> template <typename T> class Foo { public: Foo() = default; ~Foo() = default; private: std::unique_ptr<std::vector<T>> baz = std::unique_ptr<std::vector<T>>(new std::vector<T>()); }; template <typename T> class Bar { public: Bar(size_t foonum) { for (size_t n = 0; n < foonum; ++n) { bip->push_back(Foo<T>()); } } ~Bar() = default; private: std::unique_ptr<std::vector<Foo<T>>> bip = std::unique_ptr<std::vector<Foo<T>>>(new std::vector<Foo<T>>()); }; int main() { Bar<uint32_t> bar(10); return 0; } Seems like it's complaining about the new Foo<T> object not being able to be pushed back into "bip" because it can't use the default copy-constructor for that class (as unique_ptrs aren't copyable.) What's the correct way to do this? |
Victor Bazarov <v.bazarov@comcast.invalid>: Aug 24 03:53PM -0400 On 8/24/2016 3:28 PM, bitrex wrote: > to be pushed back into "bip" because it can't use the default > copy-constructor for that class (as unique_ptrs aren't copyable.) What's > the correct way to do this? The correct way to do *what*? You can't put a non-copyable object in a standard container, AFAIK, because being copy-constructible is one of the requirements for a contained type, at least in C++ 98. V -- I do not respond to top-posted replies, please don't ask |
Cholo Lennon <chololennon@hotmail.com>: Aug 24 03:46PM -0300 Can I assume (in a portable sense) that /#include "some_header"/ will always start its search from the same directory that the file that is including it? (at least in g++ and VC++ this behavior is present) The standard seems not guarantee that ("file is searched for in an implementation-defined manner"): /16.2 Source file inclusion ... 3- A preprocessing directive of the form #include " q-char-sequence" new-line causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. *The named source file is searched for in an implementation-defined manner*. If this search is not supported, or if the search fails, the directive is reprocessed as if it read # include < h-char-sequence> new-line with the identical contained sequence (including > characters, if any) from the original directive./ TIA -- Cholo Lennon Bs.As. ARG |
legalize+jeeves@mail.xmission.com (Richard): Aug 24 06:57PM [Please do not mail me a copy of your followup] Cholo Lennon <chololennon@hotmail.com> spake the secret code >Can I assume (in a portable sense) that /#include "some_header"/ will >always start its search from the same directory that the file that is >including it? (at least in g++ and VC++ this behavior is present) Not really. It depends on the search order specified by the implementation. So to answer your question you have to look at the documentation for the implementation you're using. For gcc, the documentation says that it searches the directory containing the header, then -iquote directories, then normal POSIX system directories. <https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html> For MSVC, the documentation says that it searches the directory containing the header, then directories containing currently open headers, then /I directories, then directories specified by the INCLUDE environment variable. <https://msdn.microsoft.com/en-us/library/36k2cdd4.aspx> So for these two implementations, the behavior is as you describe. I didn't look up the docs on clang as it generally adopts the behavior of gcc for compatibility, but it could also use the MSVC algorithm when invoked with MS compatibility flags. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
Cholo Lennon <chololennon@hotmail.com>: Aug 24 03:59PM -0300 On 08/24/2016 03:53 PM, Stefan Ram wrote: >> The standard seems not guarantee that ("file is searched for in an >> implementation-defined manner"): > So you answered you own question! Well, yeah, you're right, but I see a lot of C/C++ "multi-platform" code assuming that #include "..." will work as I described. That's why my question... lot of non-portable code. -- Cholo Lennon Bs.As. ARG |
Cholo Lennon <chololennon@hotmail.com>: Aug 24 04:13PM -0300 On 08/24/2016 03:57 PM, Richard wrote: > I didn't look up the docs on clang as it generally adopts the > behavior of gcc for compatibility, but it could also use the MSVC > algorithm when invoked with MS compatibility flags. Ahh OK, useful answer, thanks! -- Cholo Lennon Bs.As. ARG |
ram@zedat.fu-berlin.de (Stefan Ram): Aug 24 06:53PM >including it? (at least in g++ and VC++ this behavior is present) >The standard seems not guarantee that ("file is searched for in an >implementation-defined manner"): So you answered you own question! >/16.2 Source file inclusion Why do you continue? You already have answered your question! |
ram@zedat.fu-berlin.de (Stefan Ram): Aug 24 07:04PM >Well, yeah, you're right, but I see a lot of C/C++ "multi-platform" code >assuming that #include "..." will work as I described. That's why my >question... lot of non-portable code. I think that /usually/ things work that way (starting to search in the same directory as the file that contains the »#include "«). But maybe the C standard does not want to assume a file system with directories at all, and wanted to give permission for the source code to come from, say, a database. |
SG <s.gesemann@gmail.com>: Aug 24 04:57AM -0700 On Wednesday, August 10, 2016 at 1:27:42 AM UTC+2, Melzzzzz wrote: > > It is not really a problem to write classes this way. I am relaxed > > about it. You very soon get used to it. > Well, I'll live with it, just I am spoiled by Rust ;) Yup. I've been programming many years in C++ and started playing with Rust since 2 or 3 years ago. Rust feels like the cleaner and simpler C++ to me. Rust's move semantics is an example of simplicity and nice defaults. Keep in mind that in C++ a move constructor can even through an exception. This makes things complicated and necessitates helper functions like std::move_if_noexcept if you're interested in the strong exception safety guarantee. So, yeah, after you move from something in Rust, it's really gone in the sense that no destructor will run. In C++ you might have to add a kind of "zombie state" to your type's invariants your object has to be aware of so that it knows what and what not to do during destruction. On the other hand, this allows C++ programmers to move things out from behind references and pointers which isn't possible in safe Rust. Safe Rust only allows stack-local objects as source of moves because that's how it knows when *not* to "destroy" something that is already gone. It keeps track of it statically or via runtime drop flags (if runtime dependent branches are involved). But this is usually not a restriction in Rust. You can compensate for this with a richer container API -- for example, a vec::<T>::pop for popping off the last element of a vector... // C++ std::vector<complicyted_type> v = ...; auto mine = std::move(v.back()); v.pop(); // Rust let v: Vec<ComplicatedType> = ...; let mine = v.pop(); Kudos to the people who are responsible for Rust! |
Bo Persson <bop@gmb.dk>: Aug 24 07:23PM +0200 On 2016-08-24 13:57, SG wrote: > an exception. This makes things complicated and necessitates helper > functions like std::move_if_noexcept if you're interested in the > strong exception safety guarantee. On the other hand, this doesn't forbid storing a Type in a std::vector, even if Type's move constructor throws on odd Thursdays in october on leap-years. Flexibility before simplicity. :-) Bo Persson |
David Brown <david.brown@hesbynett.no>: Aug 24 09:05AM +0200 On 23/08/16 21:38, Victor Bazarov wrote: >> [.. blahblah ..] > Yes, please see the Standard, [lex.charset]. The first paragraph starts > with "The /basic character set/ consists". Yes, but if you read what it says, it only guarantees that the relevant characters '0', '1', etc., are available. It does /not/ guarantee that their codes are in ascending order. It just so happens that in /practical/ character sets, which will be either ASCII (at least for the 0..0x7f range - including UTF-8) or EBCDIC, the digits are in that convenient order. So as long as you are only using the code on one system, or are happy with "portable to almost anything, but not guaranteed by the standards", then it's fine to convert single digit characters to integers in this way. It might be worth putting in a range check, of course. |
Barry Schwarz <schwarzb@dqel.com>: Aug 24 01:43AM -0700 On Wed, 24 Aug 2016 09:05:52 +0200, David Brown >Yes, but if you read what it says, it only guarantees that the relevant >characters '0', '1', etc., are available. It does /not/ guarantee that >their codes are in ascending order. Yes it does. Two paragraphs later it states "In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous." -- Remove del for email |
David Brown <david.brown@hesbynett.no>: Aug 24 01:33PM +0200 On 24/08/16 10:43, Barry Schwarz wrote: > execution basic character sets, the value of each character after 0 in > the above list of decimal digits shall be one greater than the value > of the previous." You are right - I missed that. Sorry for my mistake here, and thanks for the correction. |
SG <s.gesemann@gmail.com>: Aug 24 04:16AM -0700 On Sunday, August 14, 2016 at 11:27:38 PM UTC+2, Öö Tiib wrote: > ret += x; > return ret; > } There is still some "swaptimization" possible. In your version you are forcing copy constructions with SignalSource ret(lhs); But it's usually better to have the compiler worry about how to create such a "copy" by taking the parameter by value because this allows the compiler to do some copy elisions in some cases: SignalSource operator+(SignalSource temp, SamplesType x) { // intentional call-by-value here ^ SignalSource ret; // cheap constructor ret.swap(temp); // cheap swap ret += x; return ret; // NRVO applicable } Now you might wonder why I created yet another local object. I could have worked on and returned temp directly. This has to do with the named return value optimization (NRVO). Compilers don't do that kind of optimization if the source is a function parameter ... because nobody knows how to implement that. It only works for function-local things that are NOT parameters. I would argue that this version -- provided that SignalSource has such a cheap constructor and swap function -- is preferable to your version in all cases because it's never worse but sometimes saves unnecessary copies. These tricks were quite popular in the pre-C++11 time. I recall at least two people blogging about it. Dave Abrahams had a series of articles on cpp-next.com which is not available anymore, unfortunately. Stephan T. Lavavej coined the term "swaptimization" IIRC. Though, it's been a while and my memory is fuzzy. Cheers! SG |
mark <mark@invalid.invalid>: Aug 24 02:31AM +0200 On 2016-08-24 00:15, Öö Tiib wrote: >> > } >> > } > That you can't use with gcc 4.3, it did not have 'constexpr'. I know, that's exactly my problem. This is just an illustration of the kind of simplicity and non-verbosity I would like to get. > It had variadic templates so you can perhaps make slightly > more convenient template than Richard suggests. I played around a bit with variadic templates. Getting to a dynamic array is easy, but getting compile time constants is not. Unfortunately, there isn't even a C++ standard library, so no std::tuple to get somewhat sane access to parameter pack elements. I don't see an implementation with reasonable complexity and without too much template black magic. |
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