Thursday, July 16, 2015

Digest for comp.lang.c++@googlegroups.com - 25 updates in 8 topics

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: