- Elementary question on references. - 1 Update
- clang-tidy simplify-boolean-expr check now available - 1 Update
- auto i:v as iterator - 7 Updates
- Concrete classes considered harmful - 1 Update
- What practice can get speed improvement in C++? - 8 Updates
- Why are there throw() following the delete[]? - 3 Updates
- SQL filesortcc question - 2 Updates
- Why does one 'copy ctor' is noexcept, while the other is noexcept(false)? - 2 Updates
Jorgen Grahn <grahn+nntp@snipabacken.se>: Jul 16 05:58PM On Tue, 2015-07-07, Alf P. Steinbach wrote: > In C++ a reference refers to the result of the evaluation of the > initializer expression. But (as I recall) due to a sloppy formulation of > the specification of an early version of the Algol language, [...] Etc. In C++ -- (and all real languages. except pure pre-processor languages like cpp[0]) -- expressions are evaluated where they are, in their current context. So "index" is 5, and "ref" is a reference to vec[5], whatever that is at that point in time. Like any other reference into a std::vector, it's vulnerable to invalidation, though. For example, if you add enough elements to "vec" to force it to reallocate itself, "ref" will point to something crazy and unpredictable. If you don't it's just a sane reference to vec[5]. /Jorgen [0] cpp and make are the only remaining languages with this property that I can think of. Maybe m4 as well. Too bad that one of them is embedded into every C and C++ compiler ... -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
legalize+jeeves@mail.xmission.com (Richard): Jul 16 04:57PM [Please do not mail me a copy of your followup] Hi, I've contributed a check to clang-tidy that simplifies statements involving boolean literals. The name of the check is simplify-boolean-expr. It is not enabled by default, so you must request this check to get fixes applied to your code by clang-tidy. This has been checked into the trunk of clang and I believe will be available only by compiling the clang-tools-extra subrepository of the clang/llvm tree. I've been trying to get clang-tidy included in the regular distribution, but it hasn't made it into all the packages yet AFAIK. So you'll need to compile it from source to use it. This isn't hard, but it is a fairly lengthy build. I believe this check is sufficiently robust that it should make no changes to your code that change the semantics of the code. I've run this on the clang and LLVM code bases and addressed issues and made improvements to correct and such problems encountered there. However, I would love for this check to be run on more code bases to check for any additional problems I might have missed. You can provide feedback directly to me by email or via the clang bug tracker. <https://llvm.org/bugs/> This check looks for boolean expressions involving boolean constants and simplifies them to use the appropriate boolean expression directly. Examples: `if (b == true)` becomes `if (b)` `if (b == false)` becomes `if (!b)` `if (b && true)` becomes `if (b)` `if (b && false)` becomes `if (false)` `if (b || true)` becomes `if (true)` `if (b || false)` becomes `if (b)` `e ? true : false` becomes `e` `e ? false : true` becomes `!e` `if (true) t(); else f();` becomes `t();` `if (false) t(); else f();` becomes `f();` `if (e) return true; else return false;` becomes `return e;` `if (e) return false; else return true;` becomes `return !e;` `if (e) b = true; else b = false;` becomes `b = e;` `if (e) b = false; else b = true;` becomes `b = !e;` `if (e) return true; return false;` becomes `return e;` `if (e) return false; return true;` becomes `return !e;` The resulting expression `e` is modified as follows: 1. Unnecessary parentheses around the expression are removed. 2. Negated applications of `!` are eliminated. 3. Negated applications of comparison operators are changed to use the opposite condition. 4. Implicit conversions of pointer to `bool` are replaced with explicit comparisons to `nullptr`. 5. Implicit casts to `bool` are replaced with explicit casts to `bool`. 6. Object expressions with `explicit operator bool` conversion operators are replaced with explicit casts to `bool`. Examples: 1. The ternary assignment `bool b = (i < 0) ? true : false;` has redundant parentheses and becomes `bool b = i < 0;`. 2. The conditional return `if (!b) return false; return true;` has an implied double negation and becomes `return b;`. 3. The conditional return `if (i < 0) return false; return true;` becomes `return i >= 0;`. The conditional return `if (i != 0) return false; return true;` becomes `return i == 0;`. 4. The conditional return `if (p) return true; return false;` has an implicit conversion of a pointer to `bool` and becomes `return p != nullptr;`. The ternary assignment `bool b = (i & 1) ? true : false;` has an implicit conversion of `i & 1` to `bool` and becomes `bool b = static_cast<bool>(i & 1);`. 5. The conditional return `if (i & 1) return true; else return false;` has an implicit conversion of an integer quantity `i & 1` to `bool` and becomes `return static_cast<bool>(i & 1);` 6. Given `struct X { explicit operator bool(); };`, and an instance `x` of `struct X`, the conditional return `if (x) return true; return false;` becomes `return static_cast<bool>(x);` When a conditional boolean return or assignment appears at the end of a chain of `if`, `else if` statements, the conditional statement is left unchanged unless the option `ChainedConditionalReturn` or `ChainedConditionalAssignment`, respectively, is specified as non-zero. The default value for both options is zero. -- "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> |
Ralf Goertz <me@myprovider.invalid>: Jul 16 10:39AM +0200 Hi, is it possible to have the new auto syntax for loops and get an iterator instead of a copy or a reference to the stored object itself? I would love to use the new syntax, but often I need to know what number in a vector the current object is. The following program doesn't compile. #include <vector> #include <iostream> int main() { std::vector<int> v={47,11}; for (auto i:v) { //std::cout<<i<<std::endl; std::cout<<distance(i,v.begin())<<endl; } return 0; } |
Bo Persson <bop@gmb.dk>: Jul 16 11:09AM +0200 On 2015-07-16 10:39, Ralf Goertz wrote: > } > return 0; > } If you have a reference to the element (auto&...), you can compute the difference between &i and &v[0]. Bo Persson |
Ralf Goertz <me@myprovider.invalid>: Jul 16 12:00PM +0200 Am Thu, 16 Jul 2015 11:09:51 +0200 > > } > If you have a reference to the element (auto&...), you can compute > the difference between &i and &v[0]. Thanks, that works for vector and array, but what about lists or even sets and maps? I guess I can't add another variable declaration within the "for" parenthesis like for (auto c=0, i:v) {…} |
"Öö Tiib" <ootiib@hot.ee>: Jul 16 05:17AM -0700 On Thursday, 16 July 2015 13:00:20 UTC+3, Ralf Goertz wrote: > > > } > > > return 0; > > > } It is hard to tell what you try to do because if i was iterator then this code would just output 0 and -1. It does not feel like good way for achieving such output, so there must be some sort of point to it. > > the difference between &i and &v[0]. > Thanks, that works for vector and array, but what about lists or even > sets and maps? Element's reference is cheap to convert to iterator only for containers where the elements are stored contiguously in memory (like 'std::array', 'std::vector<anything_but_bool>', 'std::valarray' or 'std::string' ) or for intrusive containers where navigation information is part of object (like Boost.Intrusive containers). > I guess I can't add another variable declaration within > the "for" parenthesis like > for (auto c=0, i:v) {...} There's no need to squeeze all things between those '(' and ')' of for loop. That works: int c = 0; for (auto i:v) {...} If you need to limit scope of c for whatever reason then limit: {int c = 0; for (auto i:v) {...}} There are no silver bullets good for all situations. New range based for loop for example is meant for cases when you need elements from container (or container-like thing). If you need iterators then use the old for loop. Behavior attempted in your original example: #include <vector> #include <iostream> #include <iterator> int main() { std::vector<int> v={47,11}; auto start = begin( v ); for ( auto i = start; i != end( v ); ++i ) { std::cout<< distance( i, start ) << std::endl; } return 0; } It may be that you need something from Boost.Range or the like but it is hard to tell without knowing what you actually want to achieve. |
Ralf Goertz <me@myprovider.invalid>: Jul 16 03:47PM +0200 Am Thu, 16 Jul 2015 05:17:03 -0700 (PDT) > On Thursday, 16 July 2015 13:00:20 UTC+3, Ralf Goertz wrote: [dequoted to make the news server happy] #include <vector> #include <iostream> #include <iterator> int main() { std::vector<int> v={47,11}; for (auto i:v) { //std::cout<<i<<std::endl; std::cout<<std::distance(i,v.begin())<<std::endl; } return 0; } > this code would just output 0 and -1. It does not feel like good way > for achieving such output, so there must be some sort of point to > it. Sure, I was merely trying to give a non compiling example (which in the OP turned out to be non-compilable not only because of the auto=/=iterator problem). And of course I meant std::distance(v.begin(),i) > Element's reference is cheap to convert to iterator only for > containers where the elements are stored contiguously in memory I know that and I have to admit that I was stretching the limits. (I actually need it only for vectors and Bo told me how to do it.) But anyway, what is bad about the idea that the auto keyword in range based for loops for container C can also be standing for C::iterator? The compiler would need to check the first appearence of the (in my case) i and deduce it is an iterator. > int c = 0; for (auto i:v) {...} > If you need to limit scope of c for whatever reason then limit: > {int c = 0; for (auto i:v) {...}} But don't you agree that this approach is somewhat less elegant? > It may be that you need something from Boost.Range or the like but it > is hard to tell without knowing what you actually want to achieve. Sometimes I need to handle the say 10th element of a vector differently than the others: for (auto &i:v) { if (&i-&v[0]==10) {…} // special stuff else {…} // do ordinary stuff } |
"Öö Tiib" <ootiib@hot.ee>: Jul 16 08:27AM -0700 On Thursday, 16 July 2015 16:47:27 UTC+3, Ralf Goertz wrote: > OP turned out to be non-compilable not only because of the > auto=/=iterator problem). And of course I meant > std::distance(v.begin(),i) Ok, so what you wanted was index of element. I post example below, later. > for loops for container C can also be standing for C::iterator? The > compiler would need to check the first appearence of the (in my case) i > and deduce it is an iterator. C++ is hopefully remaining strongly typed language and so 'auto' is remaining best to use where it is clear right away what type is meant. > > If you need to limit scope of c for whatever reason then limit: > > {int c = 0; for (auto i:v) {...}} > But don't you agree that this approach is somewhat less elegant? No. I have always considered lot of declarations and logic between parentheses of old 'for' cryptic. When there are lot of things then I prefer it as 'while' instead. Range based for is good since it lets us to write simple thing simply. > if (&i-&v[0]==10) {...} // special stuff > else {...} // do ordinary stuff > } If index matters then you can index it with Boost.Range. It works even with containers non-contiguous in memory. For example: #include <boost/range/adaptor/indexed.hpp> #include <iterator> #include <iostream> #include <set> int main() { std::set<int> input = {90,80,70,60,50,40,30,20,10}; using boost::adaptors::indexed; for ( auto const& element : input | indexed(0) ) { if ( element.index() == 5 ) { std::cout << "Special element = " << element.value() << std::endl; } else { std::cout << "Usual element = " << element.value() << std::endl; } } return 0; } Output: Usual element = 10 Usual element = 20 Usual element = 30 Usual element = 40 Usual element = 50 Special element = 60 Usual element = 70 Usual element = 80 Usual element = 90 Feels cheaper than to find out 'distance' from start of 'set' for each iteration and safer than with separate counter. |
bartekltg <bartekltg@gmail.com>: Jul 16 06:06PM +0200 On 16.07.2015 10:39, Ralf Goertz wrote: > } > return 0; > } #include <vector> #include <iostream> int main() { std::vector<int> v={47,11,11,15,154}; for (auto & i:v) { //std::cout<<i<<std::endl; std::cout<<distance(v.begin() + (&(*v.begin())-&i),v.begin())<<endl; } return 0; } Results: 0 1 2 3 4 Do NOT use it. I.m almost certain it will blow up in your face;] Just use normal for loop. The new syntax is there for your convenience, you are not force to use it if it is harder to write something. Even c-like loop with int/site_t is _sometimes_ better. bartekltg |
legalize+jeeves@mail.xmission.com (Richard): Jul 16 03:53PM [Please do not mail me a copy of your followup] Ian Collins <ian-news@hotmail.com> spake the secret code >> from Win32 then you'll want something more automated. >A lot of the code I write (and have to test) falls into that category, >hence the need to mock the system calls! Yeah, I can see that if you're writing lots of system oriented code. However, lots of C APIs are really thinly disguised objects. They have some C function you call to obtain a resource and another function you call to release a resource. So a wrapper can still be useful in these circumstances to map the C api to a more object-oriented api that ensures that resources are always properly released. Still, for unit testing that stuff you need to mock out the underlying system API calls. I've done it via both static and dynamic polymorphism to allow me to decouple myself from the specific API call. It's more tedious to do link-time substitution when the things you're mocking are in Windows DLLs. I haven't tried link-time mocking Windows DLLs myself but a coworker who tried it said that it was really quite painful. I didn't review the code he did, so I don't know exactly what the pain was, but I can imagine that link-time mocking without some sort of tool that automates the process could be quite tedious. -- "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> |
JiiPee <no@notvalid.com>: Jul 16 05:00AM +0100 On 15/07/2015 14:10, bartekltg wrote: > if (x>1) return x*factorial(x-1); > else return x; > } factorial maybe not the best example as I would do it using constexpr: constexpr long long fac(int k) { return (k == 0) ? 1 : k * fac(k - 1); } giving an instant answer (calculated compile time). |
"Öö Tiib" <ootiib@hot.ee>: Jul 16 01:04AM -0700 On Thursday, 16 July 2015 07:01:03 UTC+3, JiiPee wrote: > return (k == 0) ? 1 : k * fac(k - 1); > } > giving an instant answer (calculated compile time). Yes, factorial is always terrible example. Even see your own code. No checks of limits? You prefer to document that 'k > 20' and 'k < 0' are undefined behavior? People usually prefer (possibly compile time) diagnostics to such documentation. Even IEEE double precision can't contain 23! accurately and will overflow at 171! so usefulness of factorial is rather narrowly limited. |
bartekltg <bartekltg@gmail.com>: Jul 16 01:23PM +0200 On 16.07.2015 06:00, JiiPee wrote: > return (k == 0) ? 1 : k * fac(k - 1); > } > giving an instant answer (calculated compile time). Sure... main(){ big_int x; cin>>c; cout<<fac(x); } ;-) Also, instead int we have for example arthmetic modulo 1 178 973 853, so x can be too bit to put every possible answer in a array. bartekltg |
fl <rxjwg98@gmail.com>: Jul 16 04:34AM -0700 On Tuesday, July 14, 2015 at 10:22:54 PM UTC-7, Paavo Helde wrote: > code to get rid of bottlenecks found this way. > hth > Paavo Thanks for the replies. The question is from a new hire. The position is about programming for embedded RTOS system, although the code may be for the test bench (less embedded in some sense). I code a lot at the lower level. It is the first time I know valgrind+callgrind. |
"Öö Tiib" <ootiib@hot.ee>: Jul 16 06:54AM -0700 On Thursday, 16 July 2015 14:23:56 UTC+3, bartekltg wrote: > cout<<fac(x); > } > ;-) My psychic abilities fail me ... what is here 'big_int' and what is 'c' and is the 'fac' here called with uninitialized argument? > Also, instead int we have for example arthmetic modulo 1 178 973 853, > so x can be too bit to put every possible answer in a array. Who suggested to put answers to array? In both functions all checks are missing but neither puts anything to array. |
bartekltg <bartekltg@gmail.com>: Jul 16 05:30PM +0200 On 16.07.2015 15:54, Öö Tiib wrote: >> } >> ;-) > My psychic abilities fail me ... what is here 'big_int' and what is 'c' A type. It can be uint64_t, uint1024_t from boost or relay big integer from GMP. What do you like and need. It doesn't matter. > and is the 'fac' here called with uninitialized argument? Sorry, a typo, should be cin>>x; The point is, constexpr will help us when... the argument is constant;-) In the other case, it is just a function. >> Also, instead int we have for example arthmetic modulo 1 178 973 853, >> so x can be too bit to put every possible answer in a array. > Who suggested to put answers to array?In both functions I just skip two post: I: constexpr cant help with nonconst. somebody: you can put answers in a small array, small because 21! is outside range of uint64_t. I: for factorial yes, but not always. Look at modified problem (factorial modulo). > all checks are missing but neither puts anything to array. It doesn't matter, computing "factorial of integer munbers in modulo arithmetic" is quite artificial problem. This is only a simple example. The point is: a simple recursion will be optimized to loop. For more complex case it is hard. For example you can write quicksort as a loop (using small stack for division points), it isn't even that hard, but still most implementations (including standard library) use recursion. Can you write extended euclidean algorithm (simple algorithm from school:) as loop? I think of course you can, but it won't be pretty and wou would waste too much time. Of course, if you see something like factorial, you shouldn't event think and write it as a loop. But in other case, wasting time on rewriting algorithm as a loop I consider premature optimalization. Of course, there is always an exception. For GPU you probably start from removing all recursions ;-) bartekltg |
JiiPee <no@notvalid.com>: Jul 16 04:48PM +0100 On 16/07/2015 09:04, Öö Tiib wrote: > Even IEEE double precision can't contain 23! accurately and will > overflow at 171! so usefulness of factorial is rather narrowly > limited. I did not mean it to be perfectly done (just the idea), but you can easily change it to something like: constexpr long long unsafeFac(int k) { return (k == 0) ? 1 : k * fac(k - 1); } constexpr long long fac(int k) { return (k < 0 || k > 15) ?|||throw| |exception()| : unsafeFac(k); } Now it complains *compile* time the error (which is definitely better than a runtime version) if k is too big or too small. |
JiiPee <no@notvalid.com>: Jul 16 04:52PM +0100 On 16/07/2015 16:48, JiiPee wrote: > { > return (k < 0 || k > 15) ?|||throw| |exception()| : unsafeFac(k); > } ups, letters messed up, should be: constexpr long long fac(int k) { return (k < 0 || k > 15) ? throw exception() : unsafeFac(k); } |
fl <rxjwg98@gmail.com>: Jul 15 04:36PM -0700 On Wednesday, July 15, 2015 at 4:18:40 PM UTC-7, Ian Collins wrote: > appropriate in the declaration. > -- > Ian Collins Thanks. As you said, it is a declaration. Good. As I am a newbie to C++, I still feel it is different from a normal declaration. What role of the throw() in the declaration? I hope your further explanation can teach me more on this. Thanks again. |
Ian Collins <ian-news@hotmail.com>: Jul 16 11:44AM +1200 fl wrote: > Thanks. As you said, it is a declaration. Good. > As I am a newbie to C++, I still feel it is different from a normal > declaration. What role of the throw() in the declaration? As I said above, throw() (noexcept in modern C++) is telling you that the operators will not throw an exception. -- Ian Collins |
Bo Persson <bop@gmb.dk>: Jul 16 11:03AM +0200 On 2015-07-16 01:36, fl wrote: > As I am a newbie to C++, I still feel it is different from a normal > declaration. What role of the throw() in the declaration? > I hope your further explanation can teach me more on this. The throw-part lists the execeptions the function (or operator) is allowed to throw. Here the list is empty, meaning that it throws no exceptions. Bo Persson |
doctor@doctor.nl2k.ab.ca (The Doctor): Jul 15 11:23PM In article <d0o37bFqegtU4@mid.individual.net>, >Why are you using such an old compiler? >-- >Ian Collins Because I have not been able to have time to port up to gcc 4 or 5 on this box. -- Member - Liberal International This is doctor@@nl2k.ab.ca Ici doctor@@nl2k.ab.ca God,Queen and country!Never Satan President Republic!Beware AntiChrist rising! http://www.fullyfollow.me/rootnl2k Look at Psalms 14 and 53 on Atheism Abuse a man unjustly, and you will make friends for him. -Edgar Watson Howe |
Bo Persson <bop@gmb.dk>: Jul 16 10:58AM +0200 On 2015-07-16 01:23, The Doctor wrote: >> Ian Collins > Because I have not been able to have time to port up > to gcc 4 or 5 on this box. Yeah, it is only 12 years old. :-) Bo Persson |
fl <rxjwg98@gmail.com>: Jul 15 09:03PM -0700 Hi, C++ experts: From the following description, ........... The result is false if the expression contains at least one of the following potentially evaluated constructs: 1. call to any type of function that does not have non-throwing exception specification, unless it is a constant expression. 2. throw expression. 3. dynamic_cast expression when the target type is a reference type, and conversion needs a run time check 4. typeid expression when argument type is polymorphic class type ....... I cannot understand why the copy ctor in class U has a noexcept(false) in the below example code. Could you tell me the reason? Thanks, ............ #include <iostream> #include <utility> #include <vector> void may_throw(); void no_throw() noexcept; auto lmay_throw = []{}; auto lno_throw = []() noexcept {}; class T{ public: ~T(){} // dtor prevents move ctor // copy ctor is noexcept }; class U{ public: ~U(){} // dtor prevents move ctor // copy ctor is noexcept(false) std::vector<int> v; }; class V{ public: std::vector<int> v; }; |
"Öö Tiib" <ootiib@hot.ee>: Jul 16 01:11AM -0700 On Thursday, 16 July 2015 07:03:33 UTC+3, fl wrote: > I cannot understand why the copy ctor in class U has a noexcept(false) in > the below example code. > Could you tell me the reason? Default copy constructor just does copy-construct all bases and members. U's member v is vector whose copy constructor may throw. Therefore U's default copy constructor may also throw what v's constructor throws and so it can't be 'noexcept'. |
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