Thread: c++ primer exercise 15.31

  1. #1
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38

    Question c++ primer exercise 15.31

    Hi,
    to readers of C++ primer 5th edition. I wrote two answers for the exercise 15.31 supposing (a) answer corrects which out of the two following scenario is correct?
    Code:
    /*Exercise 15.31: Given that s1, s2, s3, and s4 are all strings, determine
     * what objects are created in the following expressions:
     *  
     *   (a) Query(s1) | Query(s2) & ~ Query(s3);
     *   (b) Query(s1) | (Query(s2) & ~ Query(s3));
     *   (c) (Query(s1) & (Query(s2)) | (Query(s3) & Query(s4)));
     *
     * a) AndQuery --- OrQuery --- WordQuery(s1)
     *       |            |
     *       |             --- WordQuery(s2)
     *       |
     *        --- NotQuery --- WordQuery(s3)
     *
     * b1) The same of (a)
     *
     * b2) OrQuery --- AndQuery --- WordQuery(s2)
     *       |           |
     *       |            --- NotQuery --- WordQuery(s3)
     *       |
     *        --- WordQuery(s1)
     *
     * c1) OrQuery --- AndQuery --- WordQuery(s4)
     *       |           |
     *       |            --- WordQuery(s3)
     *       |
     *        --- AndQuery --- WordQuery(s2)
     *               |
     *                --- WordQuery(s1)
     *
     * c2) AndQuery --- WordQuery(s4)
     *       |
     *        --- OrQuery --- WordQuery(s3)
     *               |
     *                --- OrQuery --- WordQuery(s2)
     *                       |
     *                        --- WordQuery(s1)
     */
    (b1) and (c2) answers or (b2) and (c1) answers?
    Be careful to the parenthesis when you evaluate (c) expression, it's deceiving.
    Thanks in advance

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > (a) Query(s1) | Query(s2) & ~ Query(s3);
    If you were expecting (for example) Query(s1) to always be called before Query(s2), then think again (see my reply).
    Post and Pre Increment

    Operator precedence determines how terms are combined, but the evaluation of each term is only loosely connected to precedence.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Salem View Post
    ...but the evaluation of each term is only loosely connected to precedence.
    Translation:
    The compiler is free to evaluate the terms in any order it wants. By evaluate, I mean that it can construct the Query objects in any order it wants.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38

    Question

    Quote Originally Posted by Salem View Post
    Operator precedence determines how terms are combined, but the evaluation of each term is only loosely connected to precedence.
    Those operator ( & | ~ ) are overloaded operator defined in the interface class Query. Does operator precedence apply also to overloaded operators or are they plain right-associative?
    This matters it's discussed in §15.9.1 and beyond of the book, however once builds those objects are interrelated between them in a hierarchy, the exercise asked for the hierarchy that rispect class inheritance. It must be that way otherwise dynamic binding won't work.
    Which answers are correct? Thought a) b1) c2)...
    Thanks again

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    There is no mechanism in C++ to change the precedence or associativity of the operators.
    + will always be lower than *, whether you overload it or not.

    Even if you could, there would still be no mechanism to change the order in which terms are evaluated. This is purely down to how the compiler implementer chooses to make the code generator traverse the parse tree. Factors such as "how many free registers does the processor have" figure highly in the approach taken.

    The compiler is free to do things like this
    t1 = Query(s1)
    t2 = Query(s2)
    t3 = Query(s3)
    result = t1 | t2 & ~t3;

    or this
    t3 = Query(s3)
    t3 = ~t3;
    t1 = Query(s1)
    t2 = Query(s2)
    result = t1 | t2 & t3;

    Dynamic binding only changes which function gets called, not when it gets called.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by frank67
    Those operator ( & | ~ ) are overloaded operator defined in the interface class Query. Does operator precedence apply also to overloaded operators or are they plain right-associative?
    Yes, operator precedence remains when overloading: the precedence/grouping cannot be changed by overloading. However, like precedence, "right-associative" has to do with grouping, not order of evaluation, except where the order of evaluation is constrained by the grouping.

    So, when faced with an expression like Query(s1) | Query(s2) & ~ Query(s3), one thing you can do is to (mentally) insert parentheses to make the grouping explicit.

    Quote Originally Posted by frank67
    Which answers are correct? Thought a) b1) c2)
    You might need to explain your diagrams. Perhaps it is clearer in full graphical form, but as ASCII art they look confusing to me: where do these AndQuery, OrQuery, WordQuery come from? The exercise is for you to determine "what objects are created", not the order in which they are created, though just as grouping can constrain order of evaluation, you might end up showing that along the way.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38
    Quote Originally Posted by laserlight View Post
    where do these AndQuery, OrQuery, WordQuery come from?
    First of all thanks @Salem, I didn't know what the compiler does behind the scenes.
    @Laserlight: those classes are part of the design of the back-end of the whole program, sorry the book is DRM copyright protected so I can't post the code wrote by the authors however I thought that it isn't nothing wrong discussing about answers of the book's exercises so if somebody has it he can share with me its answers.

  8. #8
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38

    Cool

    After a bit of investigation I was able to write code that using dynamic binding it nicely surrounds with parenthesis the operands of a given expression.
    Now it's easy test the expressions of the exercise and answer to it.
    Code:
    #include <iostream>
    #include <memory>
    
    using namespace std;
    
    class Backend
    {
    friend    class Frontend;
    protected:
        ~Backend() = default;
    private:
        virtual string get_expr() const = 0;
    };
    
    class Frontend
    {
    friend    Frontend operator~(const Frontend&);
    friend    Frontend operator|(const Frontend&, const Frontend&);
    friend    Frontend operator&(const Frontend&, const Frontend&);
    public:
        Frontend(const string&);
        string get_expr() const    {return f ->get_expr(); }
    private:
        Frontend(shared_ptr<Backend> b): f(b) { }
        shared_ptr<Backend> f;
    };
    
    class Operand: public Backend
    {
    friend    class Frontend;
    protected:
        Operand(const string& s): word(s) { }
        string get_expr() const    {return word;}
    private:
        string word;
    };
    inline Frontend::Frontend(const string& s): f(new Operand(s)) { }
    
    class NotExpr: public Backend
    {
    friend    Frontend operator~(const Frontend&);
    protected:
        NotExpr(const Frontend& f): front(f) { }
        string get_expr() const    {return "~(" + front.get_expr() + ")"; }
    private:
        Frontend front;
    };
    
    class OrExpr: public Backend
    {
    friend    Frontend operator|(const Frontend&, const Frontend&);
    protected:
        OrExpr(const Frontend& l, const Frontend& r, string s): lOp(l), rOp(r), symbol(s) { }
        string get_expr() const    {return "(" + lOp.get_expr() + " " + symbol + " " + rOp.get_expr() + ")"; }
    private:
        Frontend lOp, rOp;
        string symbol;
    };
    
    class AndExpr: public Backend
    {
    friend    Frontend operator&(const Frontend&, const Frontend&);
    protected:
        AndExpr(const Frontend& l, const Frontend& r, string s): lOp(l), rOp(r), symbol(s) { }
        string get_expr() const    {return "(" + lOp.get_expr() + " " + symbol + " " + rOp.get_expr() + ")"; }
    private:
        Frontend lOp, rOp;
        string symbol;
    };
    
    Frontend operator~(const Frontend& f)
    {
        return shared_ptr<Backend>(new NotExpr(f));
    }
    Frontend operator|(const Frontend& l, const Frontend& r)
    {
        return shared_ptr<Backend>(new OrExpr(l, r, "|"));
    }
    Frontend operator&(const Frontend& l, const Frontend& r)
    {
        return shared_ptr<Backend>(new AndExpr(l, r, "&"));
    }
    ostream& operator<<(ostream& os, const Frontend& f)
    {
        os << f.get_expr() << flush;
        return os;
    }
    
    int main()
    {
        using Query = Frontend;
    
        Query q=Query("s1") | Query("s2") & ~ Query("s3");
        cout << q << endl;    // prints: (s1 | (s2 & ~(s3)))
    
        q=Query("s1") | (Query("s2") & ~ Query("s3"));
        cout << q << endl;    // prints: (s1 | (s2 & ~(s3)))
    
        q=(Query("s1") & (Query("s2")) | (Query("s3") & Query("s4")));
        cout << q << endl;    // prints: ((s1 & s2) | (s3 & s4))
    
        return EXIT_SUCCESS;
    }
    The correct answers are:
    Code:
    /* Exercise 15.31: Given that s1, s2, s3, and s4 are all strings, determine
     * what objects are created in the following expressions:
     *  
     *   (a) Query(s1) | Query(s2) & ~ Query(s3);
     *   (b) Query(s1) | (Query(s2) & ~ Query(s3));
     *   (c) (Query(s1) & (Query(s2)) | (Query(s3) & Query(s4)));
     *
     * a) OrQuery --- AndQuery --- NotQuery --- WordQuery(s3)
     *       |            |
     *       |             --- WordQuery(s2)
     *       |
     *        --- WordQuery(s1)
     *
     * b) The same of a)
     *
     * c) OrQuery --- AndQuery --- WordQuery(s4)
     *       |           |
     *       |            --- WordQuery(s3)
     *       |
     *        --- AndQuery --- WordQuery(s2)
     *               |
     *                --- WordQuery(s1)
     */
    HTH

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Did you try it on different compilers?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Elysia
    Did you try it on different compilers?
    It should not make a difference: I still don't understand what these diagrams are about, but the exercise is to "determine what objects are created", so grouping, not order of evaluation, is what matters. In other words, the exercise is another way of asking the reader to insert parentheses to explicitly group every subexpression and then trace the grouping, hence frank67's idea of modifying the code such that it "nicely surrounds with parenthesis the operands of a given expression" is a good one.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38
    Quote Originally Posted by Elysia View Post
    Did you try it on different compilers?
    No I didn't. This is the compiler:
    Code:
    $ g++ --version
    g++ (Debian 4.9.2-10) 4.9.2
    Since new statement was used I checked it for memory leak, all ok.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. c++ primer exercise 15.26
    By frank67 in forum C++ Programming
    Replies: 2
    Last Post: 09-18-2015, 09:34 AM
  2. Need help with an exercise from the book "C++ Primer"
    By vizbasic2010 in forum C++ Programming
    Replies: 3
    Last Post: 06-07-2012, 07:27 AM
  3. C++ Primer
    By Imanuel in forum C++ Programming
    Replies: 3
    Last Post: 09-27-2011, 02:38 PM
  4. C++ Primer Plus
    By curt22 in forum C++ Programming
    Replies: 14
    Last Post: 07-09-2007, 07:19 PM
  5. C++ Primer 4th Edition, Problem with Exercise
    By Kaidao in forum C++ Programming
    Replies: 4
    Last Post: 07-15-2006, 11:13 AM