= operator to cast to friend class

Discussion in 'C++' started by GF, Oct 2, 2012.

  1. GF

    GF Guest

    Hello,

    I have a string class, but want to be able to assign it to some other
    frameworks class:

    I think I need to provide an global operator function, but I can't figure
    out how to declare it.


    // CODE
    #include <string>
    class mystring
    {
    public:
    mystring():m_data(NULL)
    {clear();}
    mystring(const char* s)
    {m_data=new char[strlen(s)+1]; strcpy(m_data, s);}
    // copy ctor from std::string
    mystring(const std::string& s)
    {*this = s;}
    // = operator from std::string
    const mystring& operator=(const std::string& s)
    {clear(); *this=mystring(s.c_str() ); return *this;}
    void clear()
    {delete[] m_data; m_data=new char[2]; strcpy(m_data, "");}
    private:
    char* m_data;
    };

    void test()
    {
    mystring ms;
    std::string st;
    ms = st; // fine!
    st = ms; // fail
    }
    // /CODE


    Many thanks,
    -Gernot
    GF, Oct 2, 2012
    #1
    1. Advertising

  2. On 2012-10-02 12:32 PM, GF wrote:
    > Hello,
    >
    > I have a string class, but want to be able to assign it to some other
    > frameworks class:
    >
    > I think I need to provide an global operator function, but I can't
    > figure out how to declare it.
    >
    >
    > // CODE
    > #include <string>
    > class mystring
    > {
    > public:
    > mystring():m_data(NULL)
    > {clear();}
    > mystring(const char* s)
    > {m_data=new char[strlen(s)+1]; strcpy(m_data, s);}
    > // copy ctor from std::string
    > mystring(const std::string& s)
    > {*this = s;}
    > // = operator from std::string
    > const mystring& operator=(const std::string& s)
    > {clear(); *this=mystring(s.c_str() ); return *this;}
    > void clear()
    > {delete[] m_data; m_data=new char[2]; strcpy(m_data, "");}
    > private:
    > char* m_data;
    > };
    >
    > void test()
    > {
    > mystring ms;
    > std::string st;
    > ms = st; // fine!
    > st = ms; // fail
    > }
    > // /CODE


    For the assignment st = ms; to work you need to implement the conversion
    operator to std::string

    class mystring{
    // [...]
    public:
    operator std::string()
    {
    return std::string(m_data);
    }
    };

    Use conversion operators judiciously though because they can lead to
    surprising behavior.

    Btw, just in case you didn't write your example code only to showcase
    your question and aren't aware of it: mystring is full of bugs, including

    - it leaks memory
    - the compiler generated copy constructor won't work correctly
    - mystring(const std::string& s) will delete an uninitialize pointer
    Stefan van Kessel, Oct 2, 2012
    #2
    1. Advertising

  3. On 10/2/2012 6:32 AM, GF wrote:
    > I have a string class, but want to be able to assign it to some other
    > frameworks class:
    >
    > I think I need to provide an global operator function, but I can't
    > figure out how to declare it.
    >
    >
    > // CODE
    > #include <string>
    > class mystring
    > {
    > public:
    > mystring():m_data(NULL)
    > {clear();}
    > mystring(const char* s)
    > {m_data=new char[strlen(s)+1]; strcpy(m_data, s);}
    > // copy ctor from std::string
    > mystring(const std::string& s)
    > {*this = s;}
    > // = operator from std::string
    > const mystring& operator=(const std::string& s)
    > {clear(); *this=mystring(s.c_str() ); return *this;}


    An assignment operator that returns a reference to *const*? Does not
    make sense. If you know you can assign to it, you should be able to
    call a mutating member on the result of the assignment expression,
    that's just common sense. Not to mention you should be able to do

    (a = b) = c;

    which is impossible when returning a const ref to self from a member
    that is non-const.

    > void clear()
    > {delete[] m_data; m_data=new char[2]; strcpy(m_data, "");}
    > private:
    > char* m_data;
    > };


    Your code does not adhere to the Rule of Three. Read up on it.

    >
    > void test()
    > {
    > mystring ms;
    > std::string st;
    > ms = st; // fine!
    > st = ms; // fail
    > }
    > // /CODE


    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Oct 2, 2012
    #3
  4. GF

    GF Guest

    Hi,

    code was just to show the problem - no real life code.

    Now I have an ambigiousity. It could be assignment
    std::string::eek:perator=(const char*)
    or
    mystring::eek:perator std::string()const;

    Is there a way to fix that?

    // CODE
    class mystring
    {
    public:
    mystring():m_data(NULL)
    {clear();}
    mystring(const char* s)
    {m_data=new char[strlen(s)+1]; strcpy(m_data, s);}
    // copy ctor from std::string
    mystring(const std::string& s):m_data(NULL)
    {*this = s;}
    ~mystring()
    {delete [] m_data;}

    operator std::string() const {return std::string(m_data);}
    operator const char*()const {return m_data;}

    // = operator from std::string
    const mystring& operator=(const std::string& s)
    {clear(); *this=mystring(s.c_str() ); return *this;}
    void clear()
    {delete[] m_data; m_data=new char[2]; strcpy(m_data, "");}
    private:
    char* m_data;
    };

    void test()
    {
    mystring ms;
    std::string st;
    ms = st; // fine!
    st = ms; // fail - ambigious
    }

    // /CODE





    "Stefan van Kessel" schrieb im Newsbeitrag
    news:...

    On 2012-10-02 12:32 PM, GF wrote:
    > Hello,
    >
    > I have a string class, but want to be able to assign it to some other
    > frameworks class:
    >
    > I think I need to provide an global operator function, but I can't
    > figure out how to declare it.
    >
    >
    > // CODE
    > #include <string>
    > class mystring
    > {
    > public:
    > mystring():m_data(NULL)
    > {clear();}
    > mystring(const char* s)
    > {m_data=new char[strlen(s)+1]; strcpy(m_data, s);}
    > // copy ctor from std::string
    > mystring(const std::string& s)
    > {*this = s;}
    > // = operator from std::string
    > const mystring& operator=(const std::string& s)
    > {clear(); *this=mystring(s.c_str() ); return *this;}
    > void clear()
    > {delete[] m_data; m_data=new char[2]; strcpy(m_data, "");}
    > private:
    > char* m_data;
    > };
    >
    > void test()
    > {
    > mystring ms;
    > std::string st;
    > ms = st; // fine!
    > st = ms; // fail
    > }
    > // /CODE


    For the assignment st = ms; to work you need to implement the conversion
    operator to std::string

    class mystring{
    // [...]
    public:
    operator std::string()
    {
    return std::string(m_data);
    }
    };

    Use conversion operators judiciously though because they can lead to
    surprising behavior.

    Btw, just in case you didn't write your example code only to showcase
    your question and aren't aware of it: mystring is full of bugs, including

    - it leaks memory
    - the compiler generated copy constructor won't work correctly
    - mystring(const std::string& s) will delete an uninitialize pointer
    GF, Oct 2, 2012
    #4
  5. On 2012-10-02 1:48 PM, GF wrote:
    > Hi,
    >
    > code was just to show the problem - no real life code.
    >
    > Now I have an ambigiousity. It could be assignment
    > std::string::eek:perator=(const char*)
    > or
    > mystring::eek:perator std::string()const;
    >
    > Is there a way to fix that?
    >
    > // CODE
    > class mystring
    > {
    > public:

    [...]
    > operator std::string() const {return std::string(m_data);}
    > operator const char*()const {return m_data;}

    [...]


    Supplying a operator const char*() is probably a bad idea. If you are
    intent on doing that, you could just drop the operator std::string since
    const char* is convertible to std::string by virtue of it's constructor
    taking const char* anyway.

    It's not just an accident that std::string has a member function, not a
    operator to get its c_str though. For example your class is now also
    convertible to bool and it won't be false iff the string is empty as one
    might expect but iff m_data is 0.
    Stefan van Kessel, Oct 2, 2012
    #5
  6. GF

    GF Guest


    > Supplying a operator const char*() is probably a bad idea. If you are
    > intent on doing that, you could just drop the operator std::string since
    > const char* is convertible to std::string by virtue of it's constructor
    > taking const char* anyway.


    Ah, that did the trick. Many thanks. I know of the hazard of the const char*
    operator, but it's so comfortable.
    GF, Oct 2, 2012
    #6
  7. GF

    Rui Maciel Guest

    Victor Bazarov wrote:

    > Your code does not adhere to the Rule of Three. Read up on it.


    Not adhering to the rule of three isn't the problem. In fact, not only it's
    nothing more than a rule of thumb but also it can be argued that it wasn't
    broken at all in this case, as no destructor or copy constructor was
    declared.[1]

    The one thing which was broken was RAII. It's bad form to let a class
    allocate memory from the heap and then fail to provide a proper destructor
    to clean that up.


    Rui Maciel

    [1] http://www.drdobbs.com/c-made-easier-the-rule-of-three/184401400
    Rui Maciel, Oct 2, 2012
    #7
  8. GF

    Jorgen Grahn Guest

    On Tue, 2012-10-02, GF wrote:
    ....

    > mystring(const std::string& s)
    > {*this = s;}


    > const mystring& operator=(const std::string& s)
    > {clear(); *this=mystring(s.c_str() ); return *this;}


    I didn't pay attention to the rest, but I'd do it the other way
    around: implement assignments as copy-and swap:

    mystring& operator=(const std::string& s)
    {
    mystring neu(s);
    swap(neu);
    return *this;
    }

    I'd also do what the standard containers do, and have a constructor

    template<class Iter>
    mystring(Iter first, Iter last);

    so I can construct a mystring from *any* decent character sequence.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Oct 2, 2012
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Cho
    Replies:
    1
    Views:
    299
    Jonathan Turkanis
    Mar 3, 2004
  2. Yu Lianqing
    Replies:
    1
    Views:
    634
    Leor Zolman
    Apr 4, 2004
  3. Tim Partridge
    Replies:
    1
    Views:
    706
    Sumit Rajan
    Jun 2, 2004
  4. John Goche
    Replies:
    2
    Views:
    342
    Frederick Gotham
    Sep 4, 2006
  5. Peter
    Replies:
    2
    Views:
    272
    Öö Tiib
    Jun 6, 2013
Loading...

Share This Page