Thread: c++ primer exercise 16.12

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

    Question c++ primer exercise 16.12

    I found this code on the web, after fixing some typo I got it running then I added operators to the BlobPtr template and now it doesn't compile anymore. It's already the smallest piece and it returns the same error messages of the main code I wrote.
    Could anybody take a look and give me any hints?
    Code:
    #include <iostream>
    #include <memory>
    #include <vector>
    
    using namespace std;
    
    template<typename> class BlobPtr;
    
    template<typename T> class Blob
    {
    friend    class BlobPtr<T>;
    public:
        typedef T value_type;
        typedef typename vector<T>::size_type size_type;
    
        // constructors
        Blob();
        Blob(initializer_list<T> il);
    
        // number of elements in the Blob
        size_type size() const { return data->size(); }
        bool      empty() const{ return data->empty(); }
    
        void push_back(const T& t) { data->push_back(t); }
        void push_back(T&& t)      { data->push_back(move(t)); }
        void pop_back();
    
        // element access
        T& back();
        T& operator[](size_type i);
    
        const T& back() const;
        const T& operator [](size_type i) const;
    
    private:
        shared_ptr<vector<T>> data;
        // throw msg if data[i] isn't valid
        void check(size_type i, const string &msg) const;
    };
    
    // constructors
    template<typename T> Blob<T>::Blob() : data(make_shared<vector<T>>()) { }
    template<typename T> Blob<T>::Blob(initializer_list<T> il): data(make_shared<vector<T>>(il)){ }
    
    template<typename T> void Blob<T>::check(size_type i, const string &msg) const
    {
        if(i >= data->size())
            throw out_of_range(msg);
    }
    
    template<typename T> T& Blob<T>::back()
    {
        check(0, "back on empty Blob");
        return data->back();
    }
    
    template<typename T> const T& Blob<T>::back() const
    {
        check(0, "back on empty Blob");
        return data->back();
    }
    
    
    template<typename T> T& Blob<T>::operator [](size_type i)
    {
        // if i is too big, check function will throw, preventing access to a nonexistent element
        check(i, "subscript out of range");
        return (*data)[i];
    }
    
    
    template<typename T> const T& Blob<T>::operator [](size_type i) const
    {
        // if i is too big, check function will throw, preventing access to a nonexistent element
        check(i, "subscript out of range");
        return (*data)[i];
    }
    
    template<typename T> void Blob<T>::pop_back()
    {
        check(0, "pop_back on empty Blob");
        data->pop_back();
    }
    
    template <typename> class BlobPtr;
    
    template <typename T> bool operator ==(const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);
    template <typename T> bool operator < (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);
    template <typename T> BlobPtr<T> operator+(const BlobPtr<T>&, const ptrdiff_t);
    template <typename T> BlobPtr<T> operator-(const BlobPtr<T>&, const ptrdiff_t);
    
    
    template<typename T> class BlobPtr
    {
    friend    bool operator ==<T>(const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);
    friend    bool operator < <T>(const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);
    friend    BlobPtr<T> operator+<T>(const BlobPtr<T>&, const ptrdiff_t);
    friend    BlobPtr<T> operator-<T>(const BlobPtr<T>&, const ptrdiff_t);
    public:
        BlobPtr() : curr(0) { }
        BlobPtr(Blob<T>& a, size_t sz = 0): wptr(a.data), curr(sz) { }
    
        T& operator*() const
        {
            auto p = check(curr, "dereference past end");
            return (*p)[curr];
        }
    
        BlobPtr& operator+=(const ptrdiff_t);
        BlobPtr& operator-=(const ptrdiff_t);
        // prefix
        BlobPtr& operator++();
        BlobPtr& operator--();
    
        // postfix
        BlobPtr<T> operator ++(int);
        BlobPtr<T> operator --(int);
    
    private:
        // returns  a shared_ptr to the vector if the check succeeds
        shared_ptr<vector<T>> check(size_t, const string&) const;
        weak_ptr<vector<T>> wptr;
        size_t curr;
    };
    
    template<typename T> shared_ptr<vector<T>> BlobPtr<T>::check(size_t i, const string& msg) const
    {
        auto ret = wptr.lock();    // is the vector still around?
        if (!ret)
            throw runtime_error("unbound BlobPtr");
        if (i >= ret->size())
            throw out_of_range(msg);
        return ret;    // otherwise, return a shared_ptr to the vector
    }
    // prefix ++
    template<typename T> BlobPtr<T>& BlobPtr<T>::operator ++()
    {
        // if curr already points past the end of the container, can't increment it
        check(curr, "increment past end of StrBlob");
        ++curr;
        return *this;
    }
    
    // prefix --
    template<typename T> BlobPtr<T>& BlobPtr<T>::operator --()
    {
        -- curr;
        check(curr, "decrement past begin of BlobPtr");
    
        return *this;
    }
    
    
    // postfix ++
    template<typename T> BlobPtr<T> BlobPtr<T>::operator ++(int)
    {
        BlobPtr ret = *this;
        ++*this;
    
        return ret;
    }
    
    // postfix --
    template<typename T> BlobPtr<T> BlobPtr<T>::operator --(int)
    {
        BlobPtr ret = *this;
        --*this;
    
        return ret;
    }
    
    template<typename T> bool operator==(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs)
    {
        return lhs.curr == rhs.curr;
    }
    
    template<typename T> bool operator< (const BlobPtr<T> &lhs, const BlobPtr<T> &rhs)
    {
        return lhs.curr < rhs.curr;
    }
    template <typename T> BlobPtr<T>& BlobPtr<T>::operator+=(const ptrdiff_t n)
    {
        curr += n;
        check(curr, "addition past end of BlobPtr");
        return *this;
    }
    template <typename T> BlobPtr<T>& BlobPtr<T>::operator-=(const ptrdiff_t n)
    {
        curr -= n;
        check(curr, "subtraction past begin of BlobPtr");
        return *this;
    }
    template <typename T> BlobPtr<T> BlobPtr<T>::operator+(const BlobPtr<T>& lhs, const ptrdiff_t n)
    {
        return (BlobPtr<T>(lhs)).operator+=(n);
    }
    template <typename T> BlobPtr<T> BlobPtr<T>::operator-(const BlobPtr<T>& lhs, const ptrdiff_t n)
    {
        return (BlobPtr<T>(lhs)).operator-=(n);
    }
    
    int main()
    {
        Blob<string> b;
        BlobPtr<string> bp(b);
        return EXIT_SUCCESS;
    }
    Thanks for your patience

  2. #2
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    2,158
    Post your error

  3. #3
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38
    Error messages at compile time:
    Code:
    t.cpp:193:96: error: ‘BlobPtr<T> BlobPtr< <template-parameter-1-1> >::operator+(const BlobPtr< <template-parameter-1-1> >&, std::ptrdiff_t)’ must take either zero or one argument
     template <typename T> BlobPtr<T> BlobPtr<T>::operator+(const BlobPtr<T>& lhs, const ptrdiff_t n)
                                                                                                    ^
    t.cpp:197:96: error: ‘BlobPtr<T> BlobPtr< <template-parameter-1-1> >::operator-(const BlobPtr< <template-parameter-1-1> >&, std::ptrdiff_t)’ must take either zero or one argument
     template <typename T> BlobPtr<T> BlobPtr<T>::operator-(const BlobPtr<T>& lhs, const ptrdiff_t n)
                                                                                                    ^
    In file included from /usr/include/c++/4.9/bits/stl_algobase.h:67:0,
                     from /usr/include/c++/4.9/bits/char_traits.h:39,
                     from /usr/include/c++/4.9/ios:40,
                     from /usr/include/c++/4.9/ostream:38,
                     from /usr/include/c++/4.9/iostream:39,
                     from t.cpp:1:
    /usr/include/c++/4.9/bits/stl_iterator.h: In instantiation of ‘class std::reverse_iterator<std::basic_string<char> >’:
    /usr/include/c++/4.9/bits/stl_iterator.h:334:5:   required by substitution of ‘template<class _Iterator> std::reverse_iterator<_Iterator> std::operator+(typename std::reverse_iterator<_Iterator>::difference_type, const std::reverse_iterator<_Iterator>&) [with _Iterator = std::basic_string<char>]’
    t.cpp:97:19:   required from ‘class BlobPtr<std::basic_string<char> >’
    t.cpp:205:22:   required from here
    /usr/include/c++/4.9/bits/stl_iterator.h:97:11: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<std::basic_string<char> >’
         class reverse_iterator
               ^
    /usr/include/c++/4.9/bits/stl_iterator.h:111:55: error: no type named ‘difference_type’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::difference_type difference_type;
                                                           ^
    /usr/include/c++/4.9/bits/stl_iterator.h:112:48: error: no type named ‘pointer’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::pointer  pointer;
                                                    ^
    /usr/include/c++/4.9/bits/stl_iterator.h:113:50: error: no type named ‘reference’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::reference  reference;
                                                      ^
    /usr/include/c++/4.9/bits/stl_iterator.h: In instantiation of ‘class std::move_iterator<std::basic_string<char> >’:
    /usr/include/c++/4.9/bits/stl_iterator.h:1135:5:   required by substitution of ‘template<class _Iterator> std::move_iterator<_Iterator> std::operator+(typename std::move_iterator<_Iterator>::difference_type, const std::move_iterator<_Iterator>&) [with _Iterator = std::basic_string<char>]’
    t.cpp:97:19:   required from ‘class BlobPtr<std::basic_string<char> >’
    t.cpp:205:22:   required from here
    /usr/include/c++/4.9/bits/stl_iterator.h:956:57: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::iterator_category iterator_category;
                                                             ^
    /usr/include/c++/4.9/bits/stl_iterator.h:957:52: error: no type named ‘value_type’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::value_type   value_type;
                                                        ^
    /usr/include/c++/4.9/bits/stl_iterator.h:958:55: error: no type named ‘difference_type’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::difference_type difference_type;

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    >>template <typename T> BlobPtr<T> BlobPtr<T>::operator+(const BlobPtr<T>& lhs, const ptrdiff_t n)
    The compiler is complaining because you defined the operator + as a member function in your class. Member operator + takes only one arguments because the lhs argument is implicitly *this (just like the copy assignment operator). You most likely want it to be a non-member.

    Also the case inside there is obfuscating. It would be better to construct a temporary object, e.g.:

    auto tmp(lhs);
    return tmp.operator+=(n);

    to increase code clarity.
    The rest of the error messages contains no callback to your actual code, so I can't say for certain where they come from (I haven't tried compiling). But I'm guessing it somehow stems from iterators, though I'm not sure where those iterators stem from.
    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.

  5. #5
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38
    Thanks Elysia that address me to the solution!
    However for sake of clarity two clarifications:
    First: operator+ and operator- were already non member in fact I granted they friendship to BlobPtr to access class' members.
    Second: if operator+ and operator- use implicitly this how the code you suggested could be write?
    Quote Originally Posted by Elysia View Post
    Also the case inside there is obfuscating. It would be better to construct a temporary object, e.g.:

    auto tmp(lhs);
    return tmp.operator+=(n);
    lhs parameter cannot exist in operators that they use implicitly this. I wrote definitions of operators this way:
    Code:
    template <typename T> BlobPtr<T> BlobPtr<T>::operator+(const ptrdiff_t n)
    {
            return this ->operator+=(n);
    }
    template <typename T> BlobPtr<T> BlobPtr<T>::operator-(const ptrdiff_t n)
    {
            return this ->operator-=(n);
    }
    It looks like all right now thanks again

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    As non-members, they should look like:

    template <typename T>
    BlobPtr<T> operator + (const BlobPtr<T>& lhs, const ptrdiff_t n)

    Your implementation (right now) is incorrect. You must make a copy of *this, so

    auto tmp(*this);
    return (tmp += n);

    Operator + shall not modify *this.
    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.

  7. #7
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38
    Quote Originally Posted by Elysia View Post
    As non-members, they should look like:

    template <typename T>
    BlobPtr<T> operator + (const BlobPtr<T>& lhs, const ptrdiff_t n)
    changing line 193 to:
    Code:
    template <typename T> BlobPtr<T> operator+(const BlobPtr<T>& lhs, const ptrdiff_t n)
    and line 197 to:
    Code:
    template <typename T> BlobPtr<T> operator-(const BlobPtr<T>& lhs, const ptrdiff_t n)
    It still doesn't compile I got these error messages:
    Code:
    In file included from /usr/include/c++/4.9/bits/stl_algobase.h:67:0,
                     from /usr/include/c++/4.9/bits/char_traits.h:39,
                     from /usr/include/c++/4.9/ios:40,
                     from /usr/include/c++/4.9/ostream:38,
                     from /usr/include/c++/4.9/iostream:39,
                     from torig.cpp:1:
    /usr/include/c++/4.9/bits/stl_iterator.h: In instantiation of ‘class std::reverse_iterator<std::basic_string<char> >’:
    /usr/include/c++/4.9/bits/stl_iterator.h:334:5:   required by substitution of ‘template<class _Iterator> std::reverse_iterator<_Iterator> std::operator+(typename std::reverse_iterator<_Iterator>::difference_type, const std::reverse_iterator<_Iterator>&) [with _Iterator = std::basic_string<char>]’
    torig.cpp:97:22:   required from ‘class BlobPtr<std::basic_string<char> >’
    torig.cpp:205:25:   required from here
    /usr/include/c++/4.9/bits/stl_iterator.h:97:11: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<std::basic_string<char> >’
         class reverse_iterator
               ^
    /usr/include/c++/4.9/bits/stl_iterator.h:111:55: error: no type named ‘difference_type’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::difference_type difference_type;
                                                           ^
    /usr/include/c++/4.9/bits/stl_iterator.h:112:48: error: no type named ‘pointer’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::pointer  pointer;
                                                    ^
    /usr/include/c++/4.9/bits/stl_iterator.h:113:50: error: no type named ‘reference’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::reference  reference;
                                                      ^
    /usr/include/c++/4.9/bits/stl_iterator.h: In instantiation of ‘class std::move_iterator<std::basic_string<char> >’:
    /usr/include/c++/4.9/bits/stl_iterator.h:1135:5:   required by substitution of ‘template<class _Iterator> std::move_iterator<_Iterator> std::operator+(typename std::move_iterator<_Iterator>::difference_type, const std::move_iterator<_Iterator>&) [with _Iterator = std::basic_string<char>]’
    torig.cpp:97:22:   required from ‘class BlobPtr<std::basic_string<char> >’
    torig.cpp:205:25:   required from here
    /usr/include/c++/4.9/bits/stl_iterator.h:956:57: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::iterator_category iterator_category;
                                                             ^
    /usr/include/c++/4.9/bits/stl_iterator.h:957:52: error: no type named ‘value_type’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::value_type   value_type;
                                                        ^
    /usr/include/c++/4.9/bits/stl_iterator.h:958:55: error: no type named ‘difference_type’ in ‘struct std::iterator_traits<std::basic_string<char> >’
           typedef typename __traits_type::difference_type difference_type;
                                                           ^
    Any hints really appreciated?!?
    Quote Originally Posted by Elysia View Post
    Your implementation (right now) is incorrect. You must make a copy of *this, so

    auto tmp(*this);
    return (tmp += n);

    Operator + shall not modify *this.
    You're right!

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

    Question

    I simplified the code with errors:
    Code:
     
    #include <iostream>
    #include <memory>
    #include <vector>
    #include <string>
     
    using namespace std;
     
    template<typename> class BlobPtr;
     
    template<typename T> class Blob
    {
    friend    class BlobPtr<T>;
    public:
        Blob();
    private:
        shared_ptr<vector<T>> data;
    };
    // constructors
    template<typename T> Blob<T>::Blob() : data(make_shared<vector<T>>()) { }
     
    template <typename> class BlobPtr;
    template <typename T> BlobPtr<T> operator+(const BlobPtr<T>&, const ptrdiff_t);
     
    template<typename T> class BlobPtr
    {
    friend    BlobPtr<T> operator+<T>(const BlobPtr<T>&, const ptrdiff_t);
    public:
        BlobPtr() : curr(0) { }
        BlobPtr(Blob<T>& a, size_t sz = 0): wptr(a.data), curr(sz) { }
     
        BlobPtr& operator+=(const ptrdiff_t);
    private:
        // returns  a shared_ptr to the vector if the check succeeds
        shared_ptr<vector<T>> check(size_t, const string&) const;
        weak_ptr<vector<T>> wptr;
        size_t curr;
    };
     
    template<typename T> shared_ptr<vector<T>> BlobPtr<T>::check(size_t i, const string& msg) const
    {
        auto ret = wptr.lock();    // is the vector still around?
        if (!ret)
            throw runtime_error("unbound BlobPtr");
        if (i >= ret->size())
            throw out_of_range(msg);
        return ret;    // otherwise, return a shared_ptr to the vector
    }
    template <typename T> BlobPtr<T>& BlobPtr<T>::operator+=(const ptrdiff_t n)
    {
        curr += n;
        check(curr, "addition past end of BlobPtr");
        return *this;
    }
    template <typename T> BlobPtr<T> operator+(const BlobPtr<T>& lhs, const ptrdiff_t n)
    {
        return (BlobPtr<T>(lhs)).operator+=(n);
    }
     
    int main()
    {
        Blob<string> b;
        BlobPtr<string> bp(b);
        return EXIT_SUCCESS;
    }
    g++ compiles only if I put operator+ as member of BlobPtr (the error messages are the same so I wont post it again) so the question is: operator+ must be member of a class template definitely?

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by frank67
    g++ compiles only if I put operator+ as member of BlobPtr (the error messages are the same so I wont post it again) so the question is: operator+ must be member of a class template definitely?
    No, it does not need to be a member. Your code compiles for me on g++ 4.8.4 once I comment out this line:
    Code:
    friend    BlobPtr<T> operator+<T>(const BlobPtr<T>&, const ptrdiff_t);
    If you really do want to declare operator+ as a friend at that point, then perhaps you should go for something like:
    Code:
    template<typename T1>
    friend BlobPtr<T1> operator+(const BlobPtr<T1>&, const ptrdiff_t);
    But I would not do that since it can be a non-member non-friend as-is.
    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

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by frank67 View Post
    g++ compiles only if I put operator+ as member of BlobPtr (the error messages are the same so I wont post it again) so the question is: operator+ must be member of a class template definitely?
    No, it must not. It seems the compiler is confused because you messed up the syntax.

    friend BlobPtr<T> operator+<T>(const BlobPtr<T>&, const ptrdiff_t);

    You should omit the template param (the bolded part). So it becomes:

    friend BlobPtr<T> operator + <> (const BlobPtr<T>&, const ptrdiff_t);

    See https://isocpp.org/wiki/faq/templates#template-friends.
    Nevertheless, laserlight is right. There is no need for a friend function here.

    And again, fix this line:

    return (BlobPtr<T>(lhs)).operator+=(n);

    to:

    auto tmp(lhs);
    return (lhs += n);

    For better code clarify. Avoid casts. That's going to be more important than ever going forward.
    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.

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

    Exclamation

    Quote Originally Posted by Elysia View Post
    No, it must not. It seems the compiler is confused because you messed up the syntax.
    It's what I learned... that's incredible but in the book §16.1.2 at "One-to-one friendship" I read:
    friend bool operator==<T>
    (const Blob<T>&, const Blob<T>&);
    Maybe a typo, I don't know. Omitting T now it compiles.
    I've bookmarked the remarkable faq link for future consultations.
    Quote Originally Posted by Elysia View Post
    Nevertheless, laserlight is right. There is no need for a friend function here.
    I've to check on the book why it was defined as non-member.
    Quote Originally Posted by Elysia View Post
    And again, fix this line:
    return (BlobPtr<T>(lhs)).operator+=(n);
    Despite your argumentations I like coding this way I found it self explanatory: of that class (the name must be specified) is called the copy constructor that it generate a temporary on which it's called its overloaded operator (again the name must be specified). I didn't think that it was obfuscated code, your is obfuscated.
    Seriously considering your strong advice I'll change... ah apropos maybe you meant:
    return (tmp += n)

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by frank67 View Post
    ah apropos maybe you meant:
    return (tmp += n)
    Yeah, I did. Typo there.

    What book is that you're reading? Because they don't appear to get it correct.
    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.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Since a copy must be made anyway, I prefer to write:
    Code:
    template <typename T>
    BlobPtr<T> operator+(BlobPtr<T> lhs, const ptrdiff_t n)
    {
        return lhs += n;
    }
    Quote Originally Posted by frank67
    I've to check on the book why it was defined as non-member.
    I gather that your book used a "define operator+= as a member; define operator+ as a non-member non-friend using operator+=" approach. This is correct as it means that changes due to future changes to the internals of the class template can be confined to the implementation of operator+=, rather than you having to update both functions or at least check that the latter does not need an update.

    Quote Originally Posted by frank67
    Despite your argumentations I like coding this way I found it self explanatory: of that class (the name must be specified) is called the copy constructor that it generate a temporary on which it's called its overloaded operator (again the name must be specified). I didn't think that it was obfuscated code, your is obfuscated.
    The point of operator overloading is the syntactic sugar. If you keep writing x.operator+=(y) rather than x += y, then you might as well not overload the operator. The modern use of auto is another form of syntactic sugar: the class name would already be in the parameter list, so repeating it does not add value.
    Last edited by laserlight; 09-30-2015 at 01:47 PM.
    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

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I am wary of any function that takes arguments by value when it wants a copy. Some slides I saw (Cppcon?) showed that it affects performance negatively in most compilers. The only good place to do it was in constructors for consolidating copy/move constructors into one, I think. So I'd err on the side of caution and make a copy inside the function instead.
    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.

  15. #15
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38
    Quote Originally Posted by Elysia View Post
    What book is that you're reading? Because they don't appear to get it correct.
    Cpp Primer 5th Edition this one: https://play.google.com/store/books/...d=J1HMLyxqJfgC

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. c++ primer exercise 15.31
    By frank67 in forum C++ Programming
    Replies: 10
    Last Post: 09-23-2015, 09:38 AM
  2. c++ primer exercise 15.26
    By frank67 in forum C++ Programming
    Replies: 2
    Last Post: 09-18-2015, 09:34 AM
  3. 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
  4. C++ Primer 4th Edition, Problem with Exercise
    By Kaidao in forum C++ Programming
    Replies: 4
    Last Post: 07-15-2006, 11:13 AM
  5. C++ Primer vs. Plus
    By gL_nEwB in forum C++ Programming
    Replies: 14
    Last Post: 05-09-2006, 07:01 PM