Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Can't think of a good subject

181 views
Skip to first unread message

woodb...@gmail.com

unread,
Feb 12, 2014, 10:45:10 PM2/12/14
to

I'm not sure why the behavior of the following
two functions differs here. The only difference
in these functions is in the body of the loop.

template <class R>
void Receive (::cmw::ReceiveBuffer<R>& buf
,empty_container<cmw::File>& az1)
{
int32_t count[1];
count[0]=buf.template Give<uint32_t>();
for(;count[0]>0;--count[0]){
cmw::File inst(buf); // named
}
}


template <class R>
void Receive (::cmw::ReceiveBuffer<R>& buf
,empty_container<cmw::File>& az1)
{
int32_t count[1];
count[0]=buf.template Give<uint32_t>();
for(;count[0]>0;--count[0]){
cmw::File (buf);
}
}


The first (named) version works the way I want
it to, and the second version, built with either
gcc or clang doesn't. Both compilers are
producing smaller text segments for the second
version. And the results for that version
(both compilers) are like nothing is being done
in the loop.

Can someone explain this? In another file I
have some code similar to the second version
and it works fine:

while(fgets(lineBuf,300,Fl.FlHndl)){
token=strtok(lineBuf," ");
if(strcmp("Header",token)) break;
cmw::File (strtok(nullptr,"\n ")).Marshal(buf);
}

I've simplified that loop a little, but don't
think I've removed anything important. There
are different constructors being used in these
two cases.

http://webEbenezer.net/misc/File.hh

Thanks.

Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net

Bo Persson

unread,
Feb 13, 2014, 12:00:01 PM2/13/14
to
The second version also declares a named variable, buf. Parenthesis are
optional when declaring variables.


Bo Persson


woodb...@gmail.com

unread,
Feb 13, 2014, 1:53:58 PM2/13/14
to
OK, I see what you mean. Is there a way to
tell the compiler I want an anonymous File
object to be constructed using the buf object?

Alain Ketterlin

unread,
Feb 13, 2014, 1:59:42 PM2/13/14
to
Bo Persson <b...@gmb.dk> writes:

> woodb...@gmail.com skrev 2014-02-13 04:45:

>> template <class R>
>> void Receive (::cmw::ReceiveBuffer<R>& buf
>> ,empty_container<cmw::File>& az1)
>> {
>> int32_t count[1];
>> count[0]=buf.template Give<uint32_t>();
>> for(;count[0]>0;--count[0]){
>> cmw::File inst(buf); // named
>> }
>> }
>>
>> template <class R>
>> void Receive (::cmw::ReceiveBuffer<R>& buf
>> ,empty_container<cmw::File>& az1)
>> {
>> int32_t count[1];
>> count[0]=buf.template Give<uint32_t>();
>> for(;count[0]>0;--count[0]){
>> cmw::File (buf);
>> }
>> }
>>
>> The first (named) version works the way I want
>> it to, and the second version, built with either
>> gcc or clang doesn't.

What way do you want it to "work"?

>> Both compilers are producing smaller text segments for the second
>> version. And the results for that version (both compilers) are like
>> nothing is being done in the loop.
>
> The second version also declares a named variable, buf. Parenthesis
> are optional when declaring variables.

Hmm, I think the second version creates a temporary (with buf as a
parameter to the constructor), which is not used and therefore
eliminated by the compiler. What part of the standard this behavior is
based on I don't know.

-- Alain.

red floyd

unread,
Feb 13, 2014, 2:27:30 PM2/13/14
to
Accidentally hit "reply" instead of "followup".

I think you need to put double parens around "buf".
It's very similar to the "most vexing parse" situation.

woodb...@gmail.com

unread,
Feb 13, 2014, 5:10:41 PM2/13/14
to
On Thursday, February 13, 2014 1:27:30 PM UTC-6, red floyd wrote:
> On 2/13/2014 10:53 AM, woodb...@gmail.com wrote:
>
> > On Thursday, February 13, 2014 11:00:01 AM UTC-6, Bo Persson wrote:
>
> >> The second version also declares a named variable, buf. Parenthesis are
> >> optional when declaring variables.
>
> >>
>
> > OK, I see what you mean. Is there a way to
> > tell the compiler I want an anonymous File
> > object to be constructed using the buf object?
> >
>
> Accidentally hit "reply" instead of "followup".
>

I'm not aware of a followup option. I just hit reply.

> I think you need to put double parens around "buf".

I didn't mention it in my original post, but I did
try that and just tried it again. Both compilers
produce the same output, according to the cmp command,
for

cmw::File (buf);

and

cmw::File ((buf));

I wasn't really sure why I thought of trying that,
but probably had read somewhere where that had
helped someone.


> It's very similar to the "most vexing parse" situation.

I was afraid of that also, but decided to post
because I wasn't figuring it out here.


Brian
Ebenezer Enterprises
http://webEbenezer.net

woodb...@gmail.com

unread,
Feb 13, 2014, 5:29:13 PM2/13/14
to
On Thursday, February 13, 2014 12:59:42 PM UTC-6, Alain Ketterlin wrote:
> Bo Persson <b...@gmb.dk> writes:
>
>
>
> > woodb...@gmail.com skrev 2014-02-13 04:45:
>
> >>
> >> The first (named) version works the way I want
> >> it to, and the second version, built with either
> >> gcc or clang doesn't.
>
> What way do you want it to "work"?
>

I'm looking for something analogous to this:

while(fgets(lineBuf,300,Fl.FlHndl)){
token=strtok(lineBuf," ");
if(strcmp("Header",token)) break;
cmw::File (strtok(nullptr,"\n ")).Marshal(buf);
}

That creates an anonymous File object.

> >> Both compilers are producing smaller text segments for the second
> >> version. And the results for that version (both compilers) are like
> >> nothing is being done in the loop.
> >
>
> > The second version also declares a named variable, buf. Parenthesis
> > are optional when declaring variables.
>
> Hmm, I think the second version creates a temporary (with buf as a
> parameter to the constructor), which is not used and therefore
> eliminated by the compiler.
>

That's what I was thinking might be happening originally,
but I think what Bo wrote is correct. At least according
to the cmp command, there's no difference between:

cmw::File buf;

and

cmw::File (buf);

for either compiler.

woodb...@gmail.com

unread,
Feb 13, 2014, 5:46:53 PM2/13/14
to

Just to clarify, both compilers produce the same
output, according to the cmp command, for these
three forms:

cmw::File buf;

cmw::File (buf);

cmw::File ((buf));

woodb...@gmail.com

unread,
Feb 13, 2014, 7:05:33 PM2/13/14
to
I turned on -Wshadow and that also makes me think
it's doing what Bo suggested.

/zz.middle_messages_back.hh: In member function 'void middle_messages_back::Receive(cmw::ReceiveBuffer<R>&, empty_container<cmw::File>&)':
./zz.middle_messages_back.hh:38:19: warning: declaration of 'cmw::File buf' shadows a parameter [-Wshadow]
cmw::File (buf);

Richard Damon

unread,
Feb 13, 2014, 8:09:41 PM2/13/14
to
On 2/13/14, 5:29 PM, woodb...@gmail.com wrote:
>
> I'm looking for something analogous to this:
>
> while(fgets(lineBuf,300,Fl.FlHndl)){
> token=strtok(lineBuf," ");
> if(strcmp("Header",token)) break;
> cmw::File (strtok(nullptr,"\n ")).Marshal(buf);
> }
>
> That creates an anonymous File object.
>

perhaps

0, cmw:File(buf);

might work. The key is you need to make it so it can not be parsed as a
decleration.

K. Frank

unread,
Feb 13, 2014, 10:28:39 PM2/13/14
to
Hello Brian!

On Thursday, February 13, 2014 1:53:58 PM UTC-5, woo...@woo...com wrote:
> On Thursday, February 13, 2014 11:00:01 AM UTC-6, Bo Persson wrote:
> > woo...@woo...com skrev 2014-02-13 04:45:
> >
> > > The first (named) version works the way I want
> > > it to, and the second version, built with either
> > > gcc or clang doesn't. Both compilers are
> > > producing smaller text segments for the second
> > > version. And the results for that version
> > > (both compilers) are like nothing is being done
> > > in the loop.
> >
> > The second version also declares a named variable, buf. Parenthesis are
> > optional when declaring variables.
>
> OK, I see what you mean. Is there a way to
> tell the compiler I want an anonymous File
> object to be constructed using the buf object?

If you're willing to use C++11, you can use its
so-called uniform initialization:

cmw::File{buf};

(Note the curly braces instead of parentheses.)

The curly-brace initializer list is not compatible
with the expression being interpreted as declaring
buf a variable, and so avoids the most-vexing-parse
issue.


Good luck.


K. Frank

woodb...@gmail.com

unread,
Feb 13, 2014, 11:16:10 PM2/13/14
to
On Thursday, February 13, 2014 9:28:39 PM UTC-6, K. Frank wrote:
> Hello Brian!
>
> If you're willing to use C++11, you can use its
> so-called uniform initialization:
>
> cmw::File{buf};
>
> (Note the curly braces instead of parentheses.)
>
> The curly-brace initializer list is not compatible
> with the expression being interpreted as declaring
> buf a variable, and so avoids the most-vexing-parse
> issue.
>

I've heard of that a little, but didn't think of it
here. Have tested it and it's working.

I'm using some of the newer C++ features so using
another one isn't a problem. Thank you.

Chris Vine

unread,
Feb 15, 2014, 6:23:29 AM2/15/14
to
On Thu, 13 Feb 2014 14:10:41 -0800 (PST)
woodb...@gmail.com wrote:
> On Thursday, February 13, 2014 1:27:30 PM UTC-6, red floyd wrote:
> > I think you need to put double parens around "buf".
>
> I didn't mention it in my original post, but I did
> try that and just tried it again. Both compilers
> produce the same output, according to the cmp command,
> for
>
> cmw::File (buf);
>
> and
>
> cmw::File ((buf));

What you are looking for is (cmw::File(buf));

You can see the effect of "the most vexatious parse" here with this:

----------- snip ------------

#include <iostream>

struct Test {
int a;
Test (int i): a(i) {std::cout << "In conversion constructor\n";}
Test () {std::cout << "In default constructor\n";}
};

int main () {

int b = 0;
int c = 0;

{
Test(b);
(Test(c));
}
}

Chris

Rick P

unread,
Feb 16, 2014, 9:23:20 PM2/16/14
to
On 2014-02-15 11:23:29 +0000, Chris Vine said:

> On Thu, 13 Feb 2014 14:10:41 -0800 (PST)
> woodb...@gmail.com wrote
<snip>
> You can see the effect of "the most vexatious parse" here with this:
>
> ----------- snip ------------
>
> #include <iostream>
>
> struct Test {
> int a;
> Test (int i): a(i) {std::cout << "In conversion constructor\n";}
> Test () {std::cout << "In default constructor\n";}
> };
>
> int main () {
>
> int b = 0;
> int c = 0;
>
> {
> Test(b);
> (Test(c));
> }
> }
>
> Chris

I thought I understood the most vexing parse, but then I saw this.
Could you explain how the "Test(b);" line is parsed? I thought the
most vexing parse was due to C++ treating anything that could be a
function declaration as a function declaration, but that line seems to
be parsed as a variable declaration. Thanks.

Rick

Chris Vine

unread,
Feb 17, 2014, 10:21:03 AM2/17/14
to
It is parsed as a variable declaration - namely the declaration of an
object of type Test named 'b' (and also as an object definition by
allocating stack storage for 'b'): or put another way, 'Test(b);' is
parsed as 'Test b;'. 'b' is constructed using the default constructor
of Test (not the type conversion constructor).

It is not that unreasonable a thing to do in this case. It would
usually be pointless to construct a temporary object which is dispensed
with unused at the end of the statement constructing it, so you are
unlikely to come across it. It is one of the examples in §6.8/2 of the
C++11 standard. Presumably in this case the program author was coding
for a side effect in a rather obfuscated way. Caveat obfuscator.

Chris

Rick P

unread,
Feb 17, 2014, 1:20:45 PM2/17/14
to
On 2014-02-17 15:21:03 +0000, Chris Vine said:
<snip>
>>
>> I thought I understood the most vexing parse, but then I saw this.
>> Could you explain how the "Test(b);" line is parsed? I thought the>
>> most vexing parse was due to C++ treating anything that could be a>
>> function declaration as a function declaration, but that line seems
>> to be parsed as a variable declaration. Thanks.
>
> It is parsed as a variable declaration - namely the declaration of an
> object of type Test named 'b' (and also as an object definition by
> allocating stack storage for 'b'): or put another way, 'Test(b);' is
> parsed as 'Test b;'. 'b' is constructed using the default constructor
> of Test (not the type conversion constructor).
>
> It is not that unreasonable a thing to do in this case. It would
> usually be pointless to construct a temporary object which is dispensed
> with unused at the end of the statement constructing it, so you are
> unlikely to come across it. It is one of the examples in §6.8/2 of the
> C++11 standard. Presumably in this case the program author was coding
> for a side effect in a rather obfuscated way. Caveat obfuscator.
>
> Chris

Thanks Chris for the explanation and the pointer to the standard.
There's always something new to learn about C++.

Rick

woodb...@gmail.com

unread,
Feb 17, 2014, 4:11:55 PM2/17/14
to
On Monday, February 17, 2014 9:21:03 AM UTC-6, Chris Vine wrote:
>
> It is parsed as a variable declaration - namely the declaration of an
> object of type Test named 'b' (and also as an object definition by
> allocating stack storage for 'b'): or put another way, 'Test(b);' is
> parsed as 'Test b;'. 'b' is constructed using the default constructor
> of Test (not the type conversion constructor).
>
> It is not that unreasonable a thing to do in this case. It would
> usually be pointless to construct a temporary object which is dispensed
> with unused at the end of the statement constructing it, so you are
> unlikely to come across it. It is one of the examples in §6.8/2 of the
> C++11 standard. Presumably in this case the program author was coding
> for a side effect in a rather obfuscated way. Caveat obfuscator.
>

Constructors may have side effects. In this case
it was a File class and the ctor opens a file and
writes to it.

Perhaps your argument is more with the language
itself.

Here's the modified function:

template <class R>
void Receive (::cmw::ReceiveBuffer<R>& buf
,empty_container<cmw::File>& az1)
{
int32_t count[1];
for(count[0]=buf.template Give<uint32_t>();count[0]>0;--count[0]){
cmw::File{buf};
}
}

The loop in the original version had

cmw::File inst(buf);

The variable name, inst, was superfluous in my opinion.

Brian
Ebenezer Enterprises - So far G-d has helped us.
http://webEbenezer

Chris Vine

unread,
Feb 17, 2014, 5:38:29 PM2/17/14
to
On Mon, 17 Feb 2014 13:11:55 -0800 (PST)
woodb...@gmail.com wrote:
> On Monday, February 17, 2014 9:21:03 AM UTC-6, Chris Vine wrote:
> >
> > It is parsed as a variable declaration - namely the declaration of
> > an object of type Test named 'b' (and also as an object definition
> > by allocating stack storage for 'b'): or put another way,
> > 'Test(b);' is parsed as 'Test b;'. 'b' is constructed using the
> > default constructor of Test (not the type conversion constructor).
> >
> > It is not that unreasonable a thing to do in this case. It would
> > usually be pointless to construct a temporary object which is
> > dispensed with unused at the end of the statement constructing it,
> > so you are unlikely to come across it. It is one of the examples
> > in §6.8/2 of the C++11 standard. Presumably in this case the
> > program author was coding for a side effect in a rather obfuscated
> > way. Caveat obfuscator.
> >
>
> Constructors may have side effects. In this case
> it was a File class and the ctor opens a file and
> writes to it.
>
> Perhaps your argument is more with the language
> itself.

Not really. Yours is an obfuscated way of doing it, in my view. It
would be better to have a separate object method which does the writing.

However, I don't have a problem with C++ enabling you to write
obfuscated code, if that is what you want to do.

Chris

Öö Tiib

unread,
Feb 17, 2014, 10:42:06 PM2/17/14
to
On Monday, 17 February 2014 23:11:55 UTC+2, woodb...@gmail.com wrote:
> On Monday, February 17, 2014 9:21:03 AM UTC-6, Chris Vine wrote:
> >
> > It is parsed as a variable declaration - namely the declaration of an
> > object of type Test named 'b' (and also as an object definition by
> > allocating stack storage for 'b'): or put another way, 'Test(b);' is
> > parsed as 'Test b;'. 'b' is constructed using the default constructor
> > of Test (not the type conversion constructor).
> >
> > It is not that unreasonable a thing to do in this case. It would
> > usually be pointless to construct a temporary object which is dispensed
> > with unused at the end of the statement constructing it, so you are
> > unlikely to come across it. It is one of the examples in §6.8/2 of the
> > C++11 standard. Presumably in this case the program author was coding
> > for a side effect in a rather obfuscated way. Caveat obfuscator.
>
> Constructors may have side effects. In this case
> it was a File class and the ctor opens a file and
> writes to it.

Constructor that does rather complex operations (opens and writes to files)
has to be built to fail. Constructor can signal failures only by throwing,
with globals or having object with error state. You use temporary in loop
so that removes error state and globals and leaves throwing. On your case
it seems needless complexity.

> Perhaps your argument is more with the language
> itself.

Huh? There are *functions* in C++.

> Here's the modified function:
>
> template <class R>
> void Receive (::cmw::ReceiveBuffer<R>& buf
> ,empty_container<cmw::File>& az1)
> {
> int32_t count[1];
> for(count[0]=buf.template Give<uint32_t>();count[0]>0;--count[0]){
> cmw::File{buf};
> }
> }

Not too readable what it does. Array of ints with size 1 used instead of
single int. Why? If it fails with one file in loop how it is handled?
Rest are reverted? Failed files are retried? How the whole thing resumes
after failure here?

> The loop in the original version had
>
> cmw::File inst(buf);
>
> The variable name, inst, was superfluous in my opinion.

Having array of size 1 was fine and (possibly one-letter) name was
too much to type? With or without that 'inst' it looks cryptic
(constructor is used as function) and naive (errors likely badly
handled) code, don't you see? Why it is not typical:

result = cmw::OpenAndWriteToFile(buf);
// ... handle result


woodb...@gmail.com

unread,
Mar 3, 2014, 9:58:47 PM3/3/14
to
On Tuesday, February 18, 2014 3:42:06 AM UTC, Öö Tiib wrote:
> On Monday, 17 February 2014 23:11:55 UTC+2, woodb...@gmail.com wrote:

>
> > Here's the modified function:
> >
> > template <class R>
> > void Receive (::cmw::ReceiveBuffer<R>& buf
> > ,empty_container<cmw::File>& az1)
> > {
> > int32_t count[1];
> > for(count[0]=buf.template Give<uint32_t>();count[0]>0;--count[0]){
> > cmw::File{buf};
> > }
> > }
>
> Not too readable what it does.

OK, I believe I've improved things wrt this stuff now.
Noting that function called Receive above, I used to
have this usage:

empty_container<File> outputFiles;
remoteMessages.Receive(cmwBuf, outputFiles);

Now, as a developer of empty_container, I've
moved/reworked the code that was in that Receive
function to an empty_container constructor:

template <class R>
explicit empty_container (cmw::ReceiveBuffer<R>& buf)
{
int32_t count=buf.template Give<uint32_t>();
for(; count>0; --count){
T{buf};
}
}

And with that the usage is:

empty_container<File> outputFiles(cmwBuf);


> Array of ints with size 1 used instead of
> single int. Why?

If there are nested containers, I need to have
size > 1. There's an example on my homepage.

>If it fails with one file in loop how it is handled?
> Rest are reverted? Failed files are retried? How the whole thing resumes
> after failure here?
>

Nothing would be reverted. I think it's like
a build/make process that fails. Make doesn't
revert .obj files that have been built successfully.

Up until a week or so ago I was generating a header
and a source file (.cc) for each request. After
thinking about this thread, I decided to put
everything in a header. Now there's one file
of output for each request.

Brian
Ebenezer Enterprises - Wishing Ukraine peace and prosperity.
http://webEbenezer.net
0 new messages