Friday, June 12, 2015

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

ram@zedat.fu-berlin.de (Stefan Ram): Jun 12 05:16PM

>I do not understand the »not«. The value of »,«
>is its right operand. So »(1, S::x)« is effectively
>»S::x«. Why does it say that »S::x« is /not/ odr-used?
 
Ok. In the meantime, I learned that odr-usage has to
do with S::x being used as an lvalue, not just as an
rvalue. In the line with the comma »,«, only the
/rvalue/ of S::x is used. But f(S::x) has an lvalue-
reference parameter.
ram@zedat.fu-berlin.de (Stefan Ram): Jun 12 06:14PM

Executive Summary: Where does the C++ standard describe
the effects of brace-or-equal-initializers of member-declarators
of non-static data members of primitive type?
 
I have a problem finding wording in the standard that says
that the following program will print »25«.
 
#include <iostream>
#include <ostream>
 
struct entity { double value = 25; };
 
int main(){ entity e; ::std::cout << e.value << '\n'; }
 
I am searching near
 
9.2 Class members [class.mem]
 
. There, I find:
 
member-declarator:
declarator brace-or-equal-initializer opt
 
and also
 
4 A brace-or-equal-initializer shall appear only in the
declaration of a data member.
 
. But what I'd like to read is something like this wording:
 
»The brace-or-equal-initializer is used to initialized the
data member when a new instance of the class is being created.«
 
In some cases »8.5.1 Aggregates« might be appropriate, but
not all classes with brace-or-equal-initializer in member
declarations are aggregates.
 
12.1 says: »The implicitly-defined default constructor
performs the set of initializations of the class that would
be performed by a user-written default constructor for that
class with no ctor-initializer (12.6.2) and an empty
compound-statement.« -- so we also cannot say that its
the implicitly-defined default constructor that will execute
the brace-or-equal-initializers of member-declarators.
 
So, where does the C++ standard describe the effects of
brace-or-equal-initializers of member-declarators of
non-static data members of primitive type?
ram@zedat.fu-berlin.de (Stefan Ram): Jun 12 06:32PM

>performs the set of initializations of the class that would
>be performed by a user-written default constructor for that
>class with no ctor-initializer (12.6.2) and an empty
 
12.6.2p10 also says:
 
»If a given non-static data member has both a
brace-or-equal-initializer and a mem-initializer, the
initialization specified by the mem-initializer is
performed, and the non-static data member's
brace-or-equal-initializer is ignored.«
 
This also is close. It does suggest, but does not explicitly
say that the non-static data member's
brace-or-equal-initialize /is used/ to initializie the
non-static data member in the case that a non-static data
member does /not/ have a mem-initializer.
ram@zedat.fu-berlin.de (Stefan Ram): Jun 12 06:38PM

>brace-or-equal-initialize /is used/ to initializie the
>non-static data member in the case that a non-static data
>member does /not/ have a mem-initializer.
 
Is it possible that in the case of
 
struct entity { double value = 25; };
 
the following wording 12.6.2p9 applies?
 
9 In a non-delegating constructor, if a given
potentially constructed subobject is not designated by a
meminitializer-id (including the case where there is no
mem-initializer-list because the constructor has no
ctorinitializer), then
 
(9.1) --- if the entity is a non-static data member that
has a brace-or-equal-initializer and either
 
(9.1.1) --- the constructor's class is a union (9.5),
and no other variant member of that union is designated
by a mem-initializer-id or
 
(9.1.2) --- the constructor's class is not a union, and,
if the entity is a member of an anonymous union, no
other member of that union is designated by a
mem-initializer-id,
 
the entity is initialized as specified in 8.5;
ram@zedat.fu-berlin.de (Stefan Ram): Jun 12 06:50PM

Richard writes:
>The 3rd argument in the snippet above is simply an unnamed argument of
>type "forward_iterator_tag". As mentioned in other responses, the
>standard library defines some types for the various iterators:
 
This shows that it sometimes might improve readability to write
 
#include <iterator> // struct ::std::forward_iterator_tag
...
void sort_helper(For beg, For end, struct ::std::forward_iterator_tag )
 
, because the reader now can immediately see that this
is a type name and it comes from the standard library.
 
I don't know whether the following also is legal.
 
void sort_helper(For beg, For end, typename ::std::forward_iterator_tag )
 
, but if so, it might be more appropriate so as to
make clear that it is a type while hiding the actual
implementation of the tag type as a class.
ram@zedat.fu-berlin.de (Stefan Ram): Jun 12 09:08PM

>Iterator_type<C> is a system template,
>but I can't find a description of it
 
When the type I is ::std::move_iterator< T >
or ::std::reverse_iterator< T >, then
I::iterator_type is T. So, we can define:
 
#include <iostream>
#include <ostream>
#include <array>
#include <iterator>
 
template< typename C >
using Iterator_type = typename C::iterator_type;
 
int main()
{ ::std::array< int, 2 >a={ 17, 2 };
auto iterator = ::std::begin( a );
using iterator_type = decltype( iterator );
::std::move_iterator< iterator_type >::iterator_type i0 = iterator;
::std::reverse_iterator< iterator_type >::iterator_type i1 = iterator;
Iterator_type< ::std::move_iterator< iterator_type >> i2 = iterator;
Iterator_type< ::std::reverse_iterator< iterator_type >>i3 = iterator;
::std::cout << *i0 << '\n';
::std::cout << *i1 << '\n';
::std::cout << *i2 << '\n';
::std::cout << *i3 << '\n'; }
 
17
17
17
17
ram@zedat.fu-berlin.de (Stefan Ram): Jun 12 09:19PM

>Confusing passage in C++ book
 
When you write a subject line for a post, you should use a
subject that describes the technical topic of your question.
 
For example, here a good subject would be:
 
»the value of the assignment operator«.
 
Don't use uninformative broad subjects, such as
 
»I read this in a book«,
»I have a C++ question«,
»A question about the C++ language«, or
»Here's another question from me«.
ram@zedat.fu-berlin.de (Stefan Ram): Jun 12 09:40PM

>>subject that describes the technical topic of your question.
>Yeah! You tell him, Stefan! It ought to be a subject like like "Quick
>simple question:" or "typename" or "some experiments with type names"
 
Today is the subject-line awareness day.
 
To raise the awareness of the importance of technically
specific subject lines, I indeed have posted some posts with
an intentionally uninformative subject line »Quick simple
question:«. Possibly, I will not continue this beyond this
subject-line awareness day.
ram@zedat.fu-berlin.de (Stefan Ram): Jun 12 09:53PM

>an intentionally uninformative subject line »Quick simple
>question:«. Possibly, I will not continue this beyond this
>subject-line awareness day.
 
To explain this better, I would like to remind the
newsgroup that on April 20, 2015, I already posted this:
 
|Newsgroups: comp.lang.c++
|Subject: Re: Quick Question
|From: ram@zedat.fu-berlin.de (Stefan Ram)
|
|Doug Mika <dougmmika@gmail.com> writes:
|>Subject: Quick Question
|
| You should use more specific subject lines in Usenet.
|
 
But the person addressed was not willing to consider
this suggestion on subsequent posts.
 
Instead we still get more and more subjects lines,
like, recently: »Quick simple question:«.
Paul <pepstein5@gmail.com>: Jun 12 02:13PM -0700

The passage quoted below seems to say that a=b=c; is only allowed if assignment returns a reference. This doesn't seem correct (to me). Assignment is right-associative. Even if operator = was written to return by value, it seems (to me) that a = b = c; would be fine. So I don't get why he says that you need to return a reference to allow chained assignments. I do agree that you need to return a non-const reference to be able to write (a = b) = c;
 
Thanks for your help,
 
Paul
 
BEGIN QUOTE
For IntCell, the signatures of these operations are
~IntCell( ); // Destructor
IntCell( const IntCell & rhs ); // Copy constructor
IntCell( IntCell && rhs ); // Move constructor
IntCell & operator= ( const IntCell & rhs ); // Copy assignment
IntCell & operator= ( IntCell && rhs ); // Move assignment
The return type of operator= is a reference to the invoking object, so as to allow chained assignments a=b=c. Though it would seem that the return type should be a const reference, so as to disallow nonsense such as (a=b)=c, that expression is in fact allowed in C++ even for integer types. Hence, the reference return type (rather than the const reference return type) is customarily used but is not strictly required by the language specification.
END QUOTE
Victor Bazarov <v.bazarov@comcast.invalid>: Jun 12 05:29PM -0400

On 6/12/2015 5:13 PM, Paul wrote:
> IntCell & operator= ( IntCell && rhs ); // Move assignment
> The return type of operator= is a reference to the invoking object,
> so
as to allow chained assignments a=b=c. Though it would seem that the
return type should be a const reference, so as to disallow nonsense such
as (a=b)=c, that expression is in fact allowed in C++ even for integer
types. Hence, the reference return type (rather than the const reference
return type) is customarily used but is not strictly required by the
language specification.
> END QUOTE
 
You're correct. The non-const reference return was actually to allow
calling a member function on the result of assignment, I think,
something like
 
(b = c).foo();
 
The idea was that such code should be equivalent to
 
b = c;
b.foo();
 
And, if 'b' was possible to assign to, then it should be possible to
call a non-const member function in the same scope, hence it should be
possible to combine those in a single expression. If the assignment
returned some other type, calling a non-const member would be
problematic, I think.
 
V
--
I do not respond to top-posted replies, please don't ask
Victor Bazarov <v.bazarov@comcast.invalid>: Jun 12 05:34PM -0400

On 6/12/2015 5:19 PM, Stefan Ram wrote:
>> Confusing passage in C++ book
 
> When you write a subject line for a post, you should use a
> subject that describes the technical topic of your question.
 
Yeah! You tell him, Stefan! It ought to be a subject like like "Quick
simple question:" or "typename" or "some experiments with type names"
 
There is a Russian saying "Чья бы корова мычала..."; I think Americans
use the expression "You're a fine one to talk!". Look it up!
 
> »I have a C++ question«,
> »A question about the C++ language«, or
> »Here's another question from me«.
 
V
--
I do not respond to top-posted replies, please don't ask
Noob <root@127.0.0.1>: Jun 12 10:54PM +0200

Hello,
 
I've taken a look at a medium-sized C++ legacy code-base which
crashes in several places. (NB: I'm a C coder.)
 
Turns out the program defines several large classes (~50 fields,
mostly int's or int arrays, and a few pointers). The constructor
is supposed to set everything to 0s and NULLs, but it misses a
few fields, and the program blows up when it uses one of these
uninitialized fields.
 
I was thinking: instead of trying to figure out which fields
are missing in the constructor, I could just bulldoze the
entire object:
 
std::memset(this, 0, sizeof *this);
 
(The code doesn't use the virtual keyword anywhere.)
 
Will this work as expected?
 
Regards.
Victor Bazarov <v.bazarov@comcast.invalid>: Jun 12 05:20PM -0400

On 6/12/2015 4:54 PM, Noob wrote:
 
> std::memset(this, 0, sizeof *this);
 
> (The code doesn't use the virtual keyword anywhere.)
 
> Will this work as expected?
 
You could, and we used to do that. However such practice is frowned
upon. So, don't tell anybody and put lots of warnings in the header not
to add any virtual functions or else!
 
However, in terms of software engineering, I believe it would actually
be better to add the missing initializers and also add verification (of
the same sort, like memcmp or whatever is available) and throw an
exception if the verification does not pass.
 
V
--
I do not respond to top-posted replies, please don't ask
Doug Mika <dougmmika@gmail.com>: Jun 12 10:21AM -0700

On Friday, June 12, 2015 at 11:39:46 AM UTC-5, Victor Bazarov wrote:
 
> V
> --
> I do not respond to top-posted replies, please don't ask
 
Let's stick with one question at a time:
what is "Iterator_type<C>"? Is it a reserved word like "decltype"? (No I think or I would have found it). Is it a template class? If so, what library is it in (www.cplusplus.com finds no such keyword Iterator_type)
Paavo Helde <myfirstname@osa.pri.ee>: Jun 12 12:39PM -0500

Doug Mika <dougmmika@gmail.com> wrote in
> (No I think or I would have found it). Is it a template class? If
> so, what library is it in (www.cplusplus.com finds no such keyword
> Iterator_type)
 
It looks like a template class indeed. I understand this is an example from
a book. Most probably the book assumes this is defined earlier in the code.
Probably the book contains the definition of Iterator_type somewhere. Have
you looked in the book index?
 
Anyway, it looks like a helper class which is used for deducing the needed
iterator type from the container type, maybe even for such containers as C-
style arrays.
 
hth
Paavo
Victor Bazarov <v.bazarov@comcast.invalid>: Jun 12 01:51PM -0400

On 6/12/2015 1:21 PM, Doug Mika wrote:
> Is it a reserved word like "decltype"? (No I think or I would have
> found it). Is it a template class? If so, what library is it in
> (www.cplusplus.com finds no such keyword Iterator_type)
 
It is not "a template class". There is no such thing as "a template
class". It is, in fact, a *class template*. It is not a reserved word.
It is a template that is defined somewhere. From what you have posted
I can only determine that it has at least one argument, that its
argument is a type, and I can conclude that it probably a special
constuct/template to be used in combination with other templates, like
the 'Iterator_category'.
 
Those are specialized for known containers somehow. You need to look
for more code (possibly in other sections/chapters) to see how they are
defined.
 
The Standard Library has similar templates/types defined:
 
namespace std {
struct input_iterator_tag { };
struct output_iterator_tag { };
struct forward_iterator_tag: public input_iterator_tag { };
struct bidirectional_iterator_tag: public forward_iterator_tag { };
struct random_access_iterator_tag
: public bidirectional_iterator_tag { };
}
 
For 'std::vector' its 'iterator' type is implementation-defined, but it
is such that its traits defined its category as 'random access',
probably. It's a bit more involved than the simplistic examples in the
book, but it's not impossible to follow all the definitions and unravel
them to see the relationships and how they are instantiated.
 
V
--
I do not respond to top-posted replies, please don't ask
legalize+jeeves@mail.xmission.com (Richard): Jun 12 06:41PM

[Please do not mail me a copy of your followup]
 
Doug Mika <dougmmika@gmail.com> spake the secret code
 
>QUESTION: I have never seen the paramters of a function be in the format
>"forward_iterator_tag", I have always only seen "Type instance" ie "int
>myInt". What is "forward_iterator_tag", and where is its type?
 
The 3rd argument in the snippet above is simply an unnamed argument of
type "forward_iterator_tag". As mentioned in other responses, the
standard library defines some types for the various iterators:
<http://en.cppreference.com/w/cpp/iterator/iterator_tags>
 
These types are called "tags" because they only exist to allow you to
select implementations of an algorithm based on the type of the tag.
In this case, the right implementation of the template function
sort_helper() is being selected for forward iterators through function
overloading.
 
> using Iter = Iterator_type<C>;
> sort_helper(c.begin(),c.end(),Iterator_category<Iter>{});
>}
 
Here he is using his own "Iterator_category<Iter>{}" helper as a "meta
function" -- a thing that takes a type (in this case, the type of the
iterator Iter) and returns another type (in this case, the associated
iterator category type).
 
>1)How would this sort template look if we were to not have using Iter =
>Iterator_type<C>;? What does this line do? - I have never seen it used
>in this context.
 
Iterator_type<C> is also an invocation of his own little template meta
function. I don't have my 4th edition handy here, but I remember that
he is pretty good about making sure he describes these in the text before
using them.
 
>2)What is Iterator_type and Iterator_category? I searched for these on
>www.cplusplus.com but found nothing that would make it clear.
 
They are Bjarne's helpers that simplify things slightly by eliminating
a little syntax.
--
"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>
Doug Mika <dougmmika@gmail.com>: Jun 12 01:54PM -0700

On Friday, June 12, 2015 at 12:39:37 PM UTC-5, Paavo Helde wrote:
> style arrays.
 
> hth
> Paavo
 
Iterator_type<C> is a system template, but I can't find a description of it anywhere... (The book doesn't define it). Arrrgghhh it's frustrating, it's a neat example making this even more upsetting.
Doug Mika <dougmmika@gmail.com>: Jun 12 02:05PM -0700

On Friday, June 12, 2015 at 3:54:18 PM UTC-5, Doug Mika wrote:
 
> > hth
> > Paavo
 
> Iterator_type<C> is a system template, but I can't find a description of it anywhere... (The book doesn't define it). Arrrgghhh it's frustrating, it's a neat example making this even more upsetting.
 
Come to think of it, it may be one of his own constructs, but it certainly isn't in the book - at least Adobe's find didn't locate it in my digital copy of the book....argghhh
Luca Risolia <luca.risolia@linux-projects.org>: Jun 12 07:34PM +0200

Il 12/06/2015 18:27, K.Frank ha scritto:
> double res1;
> double res2;
> thread t1 {f,some_vec,&res1}; //f(some_vec,&res1) executes in a separate
 
Sorry, typo: it's clear what I meant to say "res" is *a copy* of the
passed pointer which is "&res1" - not "res1", of course.
 
I read your "you don't want to access res1" as if one could not write
res1 (which is a pointer itself), which is clearly perfectly safe. You
probably meant to say "dereference" instead of "access".
 
However, I think what is important for the OP to notice in his example
is that what you get in f(), when it is invoked in the context of a new
thread of execution, is a const reference to **A COPY** of the original
vector passed as argument to the thread constructor. ** A COPY **
allocated in a thread-specific storage, as if by the function:
 
template <class T>
typename decay<T>::type decay_copy(T&& v) {
return std::forward<T>(v);
}
 
Many people actually fail to understand that.
 
For this reason, most of the times what you really need is to wrap the
things with std::cref() or std::ref() to share the same data between
threads.
Luca Risolia <luca.risolia@linux-projects.org>: Jun 12 08:04PM +0200

Il 12/06/2015 17:34, Doug Mika ha scritto:
> Args> explicit thread (Fn&& fn, Args&&... args);,
 
 
> don't the && imply
> "moving" of the arguments as they are/expect rvalues?)
 
No. Due to reference collapsing rules, an Arg&& becomes Arg& if you pass
an lvalue ref as argument (Arg&& & -> Arg&).
 
To answer your question then, you can "choose" by explicit casting your
arguments to lvalue-references or rvalue-references respectively.
fl <rxjwg98@gmail.com>: Jun 12 10:13AM -0700

On Friday, June 12, 2015 at 9:45:13 AM UTC-7, Victor Bazarov wrote:
 
> V
> --
> I do not respond to top-posted replies, please don't ask
Thanks for your reply. Here is other code.
 
In fact, I have a further question when I read it. 'class Complex' is
derived from Number. In the same time, class Number is its friend class.
I see this kind of thing the first time. A child class needs its parent
(base) class to operate on it?
 
 
Thanks,
 
..............
class Complex : public Number
{
friend class RealNumber;
friend class Number;
 
Complex (double d, double e);
Complex (const Complex &c);
virtual ~Complex ();
 
virtual Number operator + (Number const &n) const;
virtual Number realAdd (Number const &n) const;
virtual Number complexAdd (Number const &n) const;
double rpart, ipart;
};
 
class RealNumber : public Number
{
friend class Complex;
friend class Number;
 
RealNumber (double r);
RealNumber (const RealNumber &r);
virtual ~RealNumber ();
 
virtual Number operator + (Number const &n) const;
virtual Number realAdd (Number const &n) const;
virtual Number complexAdd (Number const &n) const;
 
double val;
};
 
/// Used only by the letters.
Number::Number (BaseConstructor): rep (0), referenceCount (1)
{}
 
/// Used by user and static factory functions.
Number::Number () : rep (0), referenceCount (0)
{}
 
/// Used by user and static factory functions.
Number::Number (const Number &n): rep (n.rep), referenceCount (0)
{
cout << "Constructing a Number using Number::Number\n";
if (n.rep)
n.rep->referenceCount++;
}
 
Number Number::makeReal (double r)
{
Number n;
n.redefine (new RealNumber (r));
return n;
}
 
Number Number::makeComplex (double rpart, double ipart)
{
Number n;
n.redefine (new Complex (rpart, ipart));
return n;
}
 
Number::~Number()
{
if (rep && --rep->referenceCount == 0)
delete rep;
}
 
Number & Number::operator = (const Number &n)
{
cout << "Assigning a Number using Number::operator=\n";
Number temp (n);
this->swap (temp);
return *this;
}
Victor Bazarov <v.bazarov@comcast.invalid>: Jun 12 01:34PM -0400

On 6/12/2015 1:13 PM, fl wrote:
> Thanks for your reply. Here is other code.
 
> In fact, I have a further question when I read it. 'class Complex' is
> derived from Number. In the same time, class Number is its friend class.
 
In order to convince yourself about the necessity of doing that (making
the derived a friend of the base and vice versa), try commenting out the
'friend' declaration and see what errors about access you get when
compiling.
 
> I see this kind of thing the first time. A child class needs its parent
> (base) class to operate on it?
 
The derived classes have no public members. All members are therefore
private. In order to even construct an object of that type you need to
either be a member or be a friend.
 
> {
> Number n;
> n.redefine (new RealNumber (r));
 
In order to compile this particular line, 'Number' has to be a friend of
'RealNumber'.
 
> {
> Number n;
> n.redefine (new Complex (rpart, ipart));
 
In order to compile this particular line, 'Number' has to be a friend of
'Complex'.
 
> this->swap (temp);
> return *this;
> }
 
I am still unsure about the 'BaseConstructor' role, but I think it's to
prevent some unpleasantness, but which unpleasantness, is still foggy
to me and I'm too lazy to take your code and compile it while playing
with c-tors and access specifiers; you can do it.
 
Try redefining Number(BaseConstructor) to be explicit Number(int).
 
V
--
I do not respond to top-posted replies, please don't ask
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jun 12 12:55AM +0100

On 11/06/2015 21:43, Paavo Helde wrote:
> inf
 
> See there. It is inf, regardless or whether you or me like it or not (I
> do!)
 
If you write code that treats division by zero as infinity then you
better keep that code to yourself; the world doesn't need it.
 
/Flibble
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: