using placement new

Discussion in 'C++' started by REH, Mar 27, 2005.

  1. REH

    REH Guest

    Hi. I want to have a union that contained various types, some of which are
    classes with constructors. I'm attempting to acheive this with placement
    new. Please tell me if the following code snippet meets the current
    standard. Should I cast char* to void* before casting to std::string*?

    Regards,

    REH


    class entry {
    public:
    enum entry_type {
    none, str
    };

    entry() : m_type(none) {}

    entry(const std::string& s) : m_type(str) {new(m_data.str)
    std::string(s);}

    // note: my compiler didn't like the use of std::string below.
    // it would only accept using a typedef of std::string or a using
    clause.
    // specifically, it didn't like the ~string(). why?
    ~entry() {using std::string; if (m_type == str)
    reinterpret_cast<string*>(m_data.str)->~string();}

    entry_type get_type() const {return m_type;}

    std::string get_str() const
    {
    if (m_type == str)
    *reinterpret_cast<string*>(m_data.str);
    else
    throw format_error(); // defined elsewhere
    }

    private:
    entry_type m_type;

    union {
    double dbl; // ensure any necessary alignment of types
    char str[sizeof(std::string)];
    } m_data;
    };
     
    REH, Mar 27, 2005
    #1
    1. Advertising

  2. REH

    Phlip Guest

    Phlip, Mar 27, 2005
    #2
    1. Advertising

  3. REH

    REH Guest

    "REH" <> wrote in message
    news:fHB1e.105690$...
    > Hi. I want to have a union that contained various types, some of which

    are
    > classes with constructors. I'm attempting to acheive this with placement
    > new. Please tell me if the following code snippet meets the current
    > standard. Should I cast char* to void* before casting to std::string*?
    >
    > Regards,
    >
    > REH
    >
    >
    > class entry {
    > public:
    > enum entry_type {
    > none, str
    > };
    >
    > entry() : m_type(none) {}
    >
    > entry(const std::string& s) : m_type(str) {new(m_data.str)
    > std::string(s);}
    >
    > // note: my compiler didn't like the use of std::string below.
    > // it would only accept using a typedef of std::string or a using
    > clause.
    > // specifically, it didn't like the ~string(). why?
    > ~entry() {using std::string; if (m_type == str)
    > reinterpret_cast<string*>(m_data.str)->~string();}
    >
    > entry_type get_type() const {return m_type;}
    >
    > std::string get_str() const
    > {
    > if (m_type == str)
    > *reinterpret_cast<string*>(m_data.str);
    > else
    > throw format_error(); // defined elsewhere
    > }
    >
    > private:
    > entry_type m_type;
    >
    > union {
    > double dbl; // ensure any necessary alignment of types
    > char str[sizeof(std::string)];
    > } m_data;
    > };
    >
    >


    Anyone see any portability and/or standard issues with the above?

    Thanks a lot.
     
    REH, Mar 28, 2005
    #3
  4. REH wrote:

    > Hi. I want to have a union that contained various types, some of which are
    > classes with constructors.



    As TC++PL is mentioning:


    "10.4.12 Unions

    A named union is defined as a struct, where every member has the same address (see C.8.2).
    A union can have member functions but not static members.

    In general, a compiler cannot know what member of a union is used; that is, the type of
    the object stored in a union is unknown. Consequently, a union may not have members with
    constructors or destructors. It wouldn’t be possible to protect that object against
    corruption or to guarantee that the right destructor is called when the union goes out of
    scope.

    Unions are best used in low-level code, or as part of the implementation of classes that
    keep track of what is stored in the union (see 10.6[20]).




    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
     
    Ioannis Vranos, Mar 28, 2005
    #4
  5. REH

    REH Guest

    "Ioannis Vranos" <> wrote in message
    news:1112043107.612258@athnrd02...
    > REH wrote:
    >
    > > Hi. I want to have a union that contained various types, some of which

    are
    > > classes with constructors.

    >
    >
    > As TC++PL is mentioning:
    >
    >
    > "10.4.12 Unions
    >
    > A named union is defined as a struct, where every member has the same

    address (see C.8.2).
    > A union can have member functions but not static members.
    >
    > In general, a compiler cannot know what member of a union is used; that

    is, the type of
    > the object stored in a union is unknown. Consequently, a union may not

    have members with
    > constructors or destructors. It wouldn’t be possible to protect that

    object against
    > corruption or to guarantee that the right destructor is called when the

    union goes out of
    > scope.
    >
    > Unions are best used in low-level code, or as part of the implementation

    of classes that
    > keep track of what is stored in the union (see 10.6[20]).
    >
    >

    Yes, I know that. The statement you commented on was just a preface to
    explaining what I was trying to acheive.
     
    REH, Mar 28, 2005
    #5
  6. REH wrote:

    > Anyone see any portability and/or standard issues with the above?



    Your code made to compile. You may check the comments:


    #include <string>


    class format_error {};

    class entry {
    public:
    enum entry_type {
    none, str
    };

    entry() : m_type(none) {}

    //==> Non-portable operation. See below.
    entry(const std::string &s) : m_type(str) {new(m_data.str)
    std::string(s);}

    // note: my compiler didn't like the use of std::string below.
    // it would only accept using a typedef of std::string or a using clause.
    // specifically, it didn't like the ~string(). why?
    ~entry() {using std::string; if (m_type == str)
    (reinterpret_cast<string *>(m_data.str))->~string();}

    entry_type get_type() const {return m_type;}

    std::string get_str()
    {
    if (m_type == str)
    *reinterpret_cast<std::string *>(m_data.str);
    else
    throw format_error(); // defined elsewhere
    }

    private:
    entry_type m_type;

    union {
    double dbl; // ensure any necessary alignment of types

    // ==> Made unsigned char since std::string is a non-POD type
    // ==> just to give it some more chance.
    // ==> Since std::string is a non-POD type though, this code is not
    // ==> portable.
    unsigned char str[sizeof(std::string)];
    } m_data;
    };


    int main()
    {
    }


    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
     
    Ioannis Vranos, Mar 28, 2005
    #6
    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. Mark P
    Replies:
    6
    Views:
    840
    James Dennett
    Apr 27, 2005
  2. Marc Mutz
    Replies:
    6
    Views:
    294
  3. Replies:
    5
    Views:
    349
    Thomas Tutone
    Apr 5, 2006
  4. Replies:
    0
    Views:
    275
  5. Replies:
    0
    Views:
    317
Loading...

Share This Page