Can't think of a good subject

W

woodbrian77

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
 
B

Bo Persson

(e-mail address removed) skrev 2014-02-13 04:45:
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.

The second version also declares a named variable, buf. Parenthesis are
optional when declaring variables.


Bo Persson
 
W

woodbrian77

(e-mail address removed) skrev 2014-02-13 04:45:



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?
 
A

Alain Ketterlin

Bo Persson said:
(e-mail address removed) 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"?
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.
 
R

red floyd

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 think you need to put double parens around "buf".
It's very similar to the "most vexing parse" situation.
 
W

woodbrian77

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
 
W

woodbrian77

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.
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.


Brian
Ebenezer Enterprises
http://webEbenezer.net
 
W

woodbrian77

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));
 
W

woodbrian77

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.

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);


Brian
Ebenezer Enterprises
http://webEbenezer.net
 
K

K. Frank

Hello Brian!

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
 
W

woodbrian77

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.
 
R

Rick P

On Thu, 13 Feb 2014 14:10:41 -0800 (PST)
(e-mail address removed) wrote
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
 
R

Rick P

On 2014-02-17 15:21:03 +0000, Chris Vine said:
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
 
W

woodbrian77

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
 
Ö

Öö Tiib

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
 
W

woodbrian77

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:

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,808
Messages
2,569,686
Members
45,453
Latest member
RamonMcCom

Latest Threads

Top