Thread: Utter confusion

  1. #1
    Registered User
    Join Date
    Aug 2008
    Location
    Belgrade, Serbia
    Posts
    163

    Utter confusion

    main.cpp
    Code:
    #include <cstdlib>
    #include <iostream>
    
    #include "int128_t.h"
    
    int main(int argc, char **argv)
    {
        using namespace std;
    
        int128_t a = 3434;
    
        cout << a << endl;
    
        return EXIT_SUCCESS;
    }
    int128_t.h
    Code:
    #include <cstdint>
    #include <iostream>
    
    class int128_t
    {
        /* Basic arithmetic */
        friend inline int128_t operator+(const int128_t &, const int128_t &);
        friend inline int128_t operator-(const int128_t &, const int128_t &);
        friend inline int128_t operator*(const int128_t &, const int128_t &);
        friend inline int128_t operator/(const int128_t &, const int128_t &);
        /* Logical comparison */
        friend inline bool operator==(const int128_t &, const int128_t &);
        template <typename T> friend inline bool operator==(const int128_t &, const T &);
        template <typename T> friend inline bool operator==(const T &, const int128_t &);
        friend inline bool operator!=(const int128_t &, const int128_t &);
        template <typename T> friend inline bool operator!=(const int128_t &, const T &);
        template <typename T> friend inline bool operator!=(const T &, const int128_t &);
        friend inline bool operator<(const int128_t &, const int128_t &);
        template <typename T> friend inline bool operator<(const int128_t &, const T &);
        template <typename T> friend inline bool operator<(const T &, const int128_t &);
        friend inline bool operator<=(const int128_t &, const int128_t &);
        template <typename T> friend inline bool operator<=(const int128_t &, const T &);
        template <typename T> friend inline bool operator<=(const T &, const int128_t &);
        friend inline bool operator>(const int128_t &, const int128_t &);
        template <typename T> friend inline bool operator>(const int128_t &, const T &);
        template <typename T> friend inline bool operator>(const T &, const int128_t &);
        friend inline bool operator>=(const int128_t &, const int128_t &);
        template <typename T> friend inline bool operator>=(const int128_t &, const T &);
        template <typename T> friend inline bool operator>=(const T &, const int128_t &);
        /* Input/Output */
        friend std::ostream &operator<<(std::ostream &ostr, const int128_t &rhs);
    
        private:
            int64_t lo, hi;
        public:
            /* Assignment and SignEqual operators */
            inline int128_t &operator=(const int128_t &);
            template <typename T> inline int128_t &operator=(const T &);
            inline void operator+=(const int128_t &);
            template <typename T> inline void operator+=(const T &);
            inline void operator-=(const int128_t &);
            template <typename T> inline void operator-=(const T &);
            inline void operator*=(const int128_t &);
            template <typename T> inline void operator*=(const T &);
            inline void operator/=(const int128_t &);
            template <typename T> inline void operator/=(const T &);
    };
    
    template <typename T>
    inline int128_t &int128_t::operator=(const T &rhs)
    {
        lo = rhs;
        hi = 0;
    
        return *this;
    }
    
    /* Basic arithmetic */
    template <typename T>
    inline void int128_t::operator+=(const T &rhs)
    {
        lo += rhs;
        hi = 0;
    }
    
    template <typename T>
    inline void int128_t::operator-=(const T &rhs)
    {
        lo -= rhs;
        hi = 0;
    }
    
    template <typename T>
    inline void int128_t::operator*=(const T &rhs)
    {
        lo *= rhs;
        hi = 0;
    }
    
    template <typename T>
    inline void int128_t::operator/=(const T &rhs)
    {
        lo += rhs;
        hi = 0;
    }
    
    
    
    /* Logical comparison */
    template <typename T>
    inline bool operator==(const int128_t &lhs, const T &rhs)
    {
        return (lhs.lo == rhs) && (lhs.hi == 0);
    }
    
    template <typename T>
    inline bool operator==(const T &lhs, const int128_t &rhs)
    {
        return (lhs == rhs.lo) && (rhs.hi == 0);
    }
    
    
    template <typename T>
    inline bool operator!=(const int128_t &lhs, const T &rhs)
    {
        return (lhs.lo != rhs) || (lhs.hi != 0);
    }
    
    template <typename T>
    inline bool operator!=(const T &lhs, const int128_t &rhs)
    {
        return (lhs != rhs.lo) || (rhs.hi != 0);
    }
    
    
    template <typename T>
    inline bool operator<(const int128_t &lhs, const T &rhs)
    {
        return (lhs.lo < rhs) && (lhs.hi == 0);
    }
    
    template <typename T>
    inline bool operator<(const T &lhs, const int128_t &rhs)
    {
        return (lhs < rhs.lo) && (rhs.hi == 0);
    }
    
    
    template <typename T>
    inline bool operator<=(const int128_t &lhs, const T &rhs)
    {
        return (lhs.lo <= rhs) && (lhs.hi == 0);
    }
    
    template <typename T>
    inline bool operator<=(const T &lhs, const int128_t &rhs)
    {
        return (lhs <= rhs.lo) && (rhs.hi == 0);
    }
    
    
    template <typename T>
    inline bool operator>(const int128_t &lhs, const T &rhs)
    {
        return (lhs.lo > rhs) && (lhs.hi == 0);
    }
    
    template <typename T>
    inline bool operator>(const T &lhs, const int128_t &rhs)
    {
        return (lhs > rhs.lo) && (rhs.hi == 0);
    }
    
    
    template <typename T>
    inline bool operator>=(const int128_t &lhs, const T &rhs)
    {
        return (lhs.lo >= rhs) && (lhs.hi == 0);
    }
    
    template <typename T>
    inline bool operator>=(const T &lhs, const int128_t &rhs)
    {
        return (lhs >= rhs.lo) && (rhs.hi == 0);
    }
    int128_t.cpp
    Code:
    #include "int128_t.h"
    
    /* Basic arithmetic */
    inline int128_t &int128_t::operator=(const int128_t &rhs)
    {
        lo = rhs.lo;
        hi = rhs.hi;
    
        return *this;
    }
    
    inline int128_t operator+(const int128_t &a, const int128_t &b)
    {
        int128_t x;
    
        x.lo = a.lo + b.lo;
        x.hi = a.hi + b.hi;
    
        return x;
    }
    
    inline int128_t operator-(const int128_t &a, const int128_t &b)
    {
        int128_t x;
    
        x.lo = a.lo - b.lo;
        x.hi = a.hi - b.hi;
    
        return x;
    }
    
    inline int128_t operator*(const int128_t &a, const int128_t &b)
    {
        int128_t x;
    
        x.lo = a.lo * b.lo;
        x.hi = a.hi * b.hi;
    
        return x;
    }
    
    inline int128_t operator/(const int128_t &a, const int128_t &b)
    {
        int128_t x;
    
        x.lo = a.lo / b.lo;
        if(b.hi == 0) x.hi = 0;
        else x.hi = a.hi / b.hi;
    
        return x;
    }
    
    inline void int128_t::operator+=(const int128_t &rhs)
    {
        lo += rhs.lo;
        hi += rhs.hi;
    }
    
    inline void int128_t::operator-=(const int128_t &rhs)
    {
        lo -= rhs.lo;
        hi -= rhs.hi;
    }
    
    inline void int128_t::operator*=(const int128_t &rhs)
    {
        lo *= rhs.lo;
        hi *= rhs.hi;
    }
    
    inline void int128_t::operator/=(const int128_t &rhs)
    {
        lo /= rhs.lo;
        if(rhs.hi == 0) hi = 0;
        else hi /= rhs.hi;
    }
    
    /* Logical comparison */
    inline bool operator==(const int128_t &lhs, const int128_t &rhs)
    {
        return (lhs.lo == rhs.lo) && (lhs.hi == rhs.hi);
    }
    
    inline bool operator!=(const int128_t &lhs, const int128_t &rhs)
    {
        return (lhs.lo != rhs.lo) || (lhs.hi != rhs.hi);
    }
    
    inline bool operator<(const int128_t &lhs, const int128_t &rhs)
    {
        return lhs.hi < rhs.hi;
    }
    
    inline bool operator<=(const int128_t &lhs, const int128_t &rhs)
    {
        return lhs.hi <= rhs.hi;
    }
    
    inline bool operator>(const int128_t &lhs, const int128_t &rhs)
    {
        return lhs.hi > rhs.hi;
    }
    
    inline bool operator>=(const int128_t &lhs, const int128_t &rhs)
    {
        return lhs.hi >= rhs.hi;
    }
    
    /* Input/Output */
    std::ostream &operator<<(std::ostream& ostr, const int128_t &rhs)
    {
        if(rhs.hi == 0) ostr << rhs.lo;
    
        return ostr;
    }

    I can't find out what's the problem. When trying to assing 3434 to a in main.cpp I get an error: "conversion from ‘int’ to non-scalar type ‘int128_t’ requested" although I have made a template to accept ints and such. Something is obviously wrong, but I don't know what. I'm weary of swimming trough code and diving in the internet. There are probably tons of errors and some enlightenment on this matter is more than welcome.
    Vanity of vanities, saith the Preacher, vanity of vanities; all is vanity.
    What profit hath a man of all his labour which he taketh under the sun?
    All the rivers run into the sea; yet the sea is not full; unto the place from whence the rivers come, thither they return again.
    For in much wisdom is much grief: and he that increaseth knowledge increaseth sorrow.

  2. #2
    Just a pushpin. bernt's Avatar
    Join Date
    May 2009
    Posts
    426
    Code:
    int128_t a = 3434;
    Initialization like this uses the copy constructor, rather than operator=.
    Consider this post signed

  3. #3
    Registered User
    Join Date
    Aug 2008
    Location
    Belgrade, Serbia
    Posts
    163
    Thanks for the tip, some thing are much clearer now. I've added the copy constructor and removed those inlines for now, everything works perfectly. One question, do I have to declare multiple version of functions like this:

    Code:
    template  friend bool operator>=(const int128_t &, const T &);
    template  friend bool operator>=(const T &, const int128_t &);
    It seems logical to do so, but I'm asking just in case.
    Vanity of vanities, saith the Preacher, vanity of vanities; all is vanity.
    What profit hath a man of all his labour which he taketh under the sun?
    All the rivers run into the sea; yet the sea is not full; unto the place from whence the rivers come, thither they return again.
    For in much wisdom is much grief: and he that increaseth knowledge increaseth sorrow.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by bernt
    Initialization like this uses the copy constructor, rather than operator=.
    Not really: it would use the most appropriate constructor, not the copy constructor, but no appropriate constructor was defined, hence the error. This class does not need to have the copy constructor (or copy assignment operator or destructor) explicitly defined.

    Quote Originally Posted by hauzer
    One question, do I have to declare multiple version of functions like this:
    If you do not want to rely on implicit conversions, yes. Instead of making these friends:
    Code:
    friend inline int128_t operator+(const int128_t &, const int128_t &);
    friend inline int128_t operator-(const int128_t &, const int128_t &);
    friend inline int128_t operator*(const int128_t &, const int128_t &);
    friend inline int128_t operator/(const int128_t &, const int128_t &);
    make them non-member non-friends and implement them using the assignment versions, e.g., implement operator+ in terms of operator+=.

    Likewise, I feel that you might as well make these const member functions:
    Code:
    bool operator==(const int128_t &, const int128_t &);
    template <typename T> bool operator==(const int128_t &, const T &);
    then implement the other operator== function template as a non-member non-friend using the member version of the function template. (Though if you did not have the template versions, then keeping the non-template version as a friend would be good, in my opinion.)

    See if you can apply the same "prefer non-member non-friends, otherwise prefer members to friends" approach to the other functions without loss of efficiency. You could even consider implementing operator!= in terms of operator==, and say, >= in terms of < and > in terms of <= (though you could implement all in terms of just < if you wanted to, with small loss of efficiency).

    Also, inline functions should be defined in the header. You will not break the one definition rule because they are declared inline. If you define a member function in the class definition (I noticed you did not do so though), it is already inline, so declaring it inline would be redundant.

    EDIT:
    By the way, I am curious as to the correctness of your implementation, e.g., if you are adding two numbers together, don't you have to care about whether the addition of the lower half overflows so as to pre-emptively perform carry over?
    Last edited by laserlight; 10-24-2011 at 08:18 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

  5. #5
    Registered User
    Join Date
    Aug 2008
    Location
    Belgrade, Serbia
    Posts
    163
    Quote Originally Posted by laserlight View Post
    If you do not want to rely on implicit conversions, yes. Instead of making these friends:
    Code:
    friend inline int128_t operator+(const int128_t &, const int128_t &);
    friend inline int128_t operator-(const int128_t &, const int128_t &);
    friend inline int128_t operator*(const int128_t &, const int128_t &);
    friend inline int128_t operator/(const int128_t &, const int128_t &);
    make them non-member non-friends and implement them using the assignment versions, e.g., implement operator+ in terms of operator+=.
    Now that's OOP thinking, I like that.

    Quote Originally Posted by laserlight View Post
    Likewise, I feel that you might as well make these const member functions:
    Code:
    bool operator==(const int128_t &, const int128_t &);
     template <typename T> bool operator==(const int128_t &, const T &);
    then implement the other operator== function template as a non-member non-friend using the member version of the function template. (Though if you did not have the template versions, then keeping the non-template version as a friend would be good, in my opinion.)
    I'm not sure I understand what you mean here.

    Quote Originally Posted by laserlight View Post
    See if you can apply the same "prefer non-member non-friends, otherwise prefer members to friends" approach to the other functions without loss of efficiency. You could even consider implementing operator!= in terms of operator==, and say, >= in terms of < and > in terms of <= (though you could implement all in terms of just < if you wanted to, with small loss of efficiency).
    I will try to apply that and see how it turns out.

    Quote Originally Posted by laserlight View Post
    Also, inline functions should be defined in the header.
    Yes, it was an error made in haste; I've removed the inline attribute from all functions for now.

    Quote Originally Posted by laserlight View Post
    By the way, I am curious as to the correctness of your implementation, e.g., if you are adding two numbers together, don't you have to care about whether the addition of the lower half overflows so as to pre-emptively perform carry over?
    It's absolutely uncorrect and it's just a placeholder until I design the class.
    I come from a strict-C and non-OOP background so grasping these advanced techniques is not a simple task. Although I know the common OOP concepts both in theory and practice, the advanced ones demand more thourough writing and practicing. I like to learn from firsthand experience rather than applying already thought-out alghorithms and designs. It certainly is unproductive at most times, but that's just who I am. Learning for the sake of it is never my goal, no matter how absurd that sounds.
    Vanity of vanities, saith the Preacher, vanity of vanities; all is vanity.
    What profit hath a man of all his labour which he taketh under the sun?
    All the rivers run into the sea; yet the sea is not full; unto the place from whence the rivers come, thither they return again.
    For in much wisdom is much grief: and he that increaseth knowledge increaseth sorrow.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by hauzer View Post
    I'm not sure I understand what you mean here.
    It means that if you have a == b, then equivalently, b == a.
    So if a has member operator == (const B&), then we could use the above fact by writing a free function (ie, not a member function) operator == (const B&, const A&) that simply returns true if a == b (the member function can perform that task!).
    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
    Aug 2008
    Location
    Belgrade, Serbia
    Posts
    163
    Quote Originally Posted by Elysia View Post
    It means that if you have a == b, then equivalently, b == a.
    So if a has member operator == (const B&), then we could use the above fact by writing a free function (ie, not a member function) operator == (const B&, const A&) that simply returns true if a == b (the member function can perform that task!).
    That makes sense. I have just got cought in the wording. Thanks.
    Vanity of vanities, saith the Preacher, vanity of vanities; all is vanity.
    What profit hath a man of all his labour which he taketh under the sun?
    All the rivers run into the sea; yet the sea is not full; unto the place from whence the rivers come, thither they return again.
    For in much wisdom is much grief: and he that increaseth knowledge increaseth sorrow.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ confusion
    By Eirik in forum Windows Programming
    Replies: 14
    Last Post: 04-29-2009, 01:54 PM
  2. Utter newb?: Program crashes after input
    By deductible in forum C++ Programming
    Replies: 5
    Last Post: 12-13-2008, 10:27 PM
  3. Utter beginner question about using notepad for c++
    By Borodin in forum C++ Programming
    Replies: 8
    Last Post: 08-18-2008, 04:08 PM
  4. Confusion
    By Nestor in forum C++ Programming
    Replies: 4
    Last Post: 06-20-2008, 02:17 PM
  5. Utter confusion, resulting from SYSTEMTIME
    By Tronic in forum Windows Programming
    Replies: 8
    Last Post: 01-04-2005, 08:21 PM