Can't think of a good subject

Discussion in 'C++' started by woodbrian77, Feb 13, 2014.

  1. woodbrian77

    woodbrian77 Guest

    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
     
    woodbrian77, Feb 13, 2014
    #1
    1. Advertisements

  2. woodbrian77

    Bo Persson Guest

    skrev 2014-02-13 04:45:
    The second version also declares a named variable, buf. Parenthesis are
    optional when declaring variables.


    Bo Persson
     
    Bo Persson, Feb 13, 2014
    #2
    1. Advertisements

  3. woodbrian77

    woodbrian77 Guest

    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?
     
    woodbrian77, Feb 13, 2014
    #3
  4. What way do you want it to "work"?
    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.
     
    Alain Ketterlin, Feb 13, 2014
    #4
  5. woodbrian77

    red floyd Guest

    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.
     
    red floyd, Feb 13, 2014
    #5
  6. woodbrian77

    woodbrian77 Guest

    I'm not aware of a followup option. I just hit reply.
    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.

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


    Brian
    Ebenezer Enterprises
    http://webEbenezer.net
     
    woodbrian77, Feb 13, 2014
    #6
  7. woodbrian77

    woodbrian77 Guest

    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.
    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
     
    woodbrian77, Feb 13, 2014
    #7
  8. woodbrian77

    woodbrian77 Guest

    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));
     
    woodbrian77, Feb 13, 2014
    #8
  9. woodbrian77

    woodbrian77 Guest

    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
     
    woodbrian77, Feb 14, 2014
    #9
  10. woodbrian77

    K. Frank Guest

    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.


    Good luck.


    K. Frank
     
    K. Frank, Feb 14, 2014
    #10
  11. woodbrian77

    woodbrian77 Guest

    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.
     
    woodbrian77, Feb 14, 2014
    #11
  12. woodbrian77

    Rick P Guest

    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
     
    Rick P, Feb 17, 2014
    #12
  13. woodbrian77

    Rick P Guest

    On 2014-02-17 15:21:03 +0000, Chris Vine said:
    Thanks Chris for the explanation and the pointer to the standard.
    There's always something new to learn about C++.

    Rick
     
    Rick P, Feb 17, 2014
    #13
  14. woodbrian77

    woodbrian77 Guest

    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
     
    woodbrian77, Feb 17, 2014
    #14
  15. woodbrian77

    Öö Tiib Guest

    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.
    Huh? There are *functions* in C++.
    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?
    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
     
    Öö Tiib, Feb 18, 2014
    #15
  16. woodbrian77

    woodbrian77 Guest

    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:

    If there are nested containers, I need to have
    size > 1. There's an example on my homepage.
    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
     
    woodbrian77, Mar 4, 2014
    #16
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.