Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3443946
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T08:51:14+00:00 2026-05-18T08:51:14+00:00

I’ve got some code that I’ve been using successfully for some years to implement

  • 0

I’ve got some code that I’ve been using successfully for some years to implement a “variant-type object”; that is, a C++ object that can hold a values of various types, but only uses (approximately) as much memory as the largest of the possible types. The code is similar in spirit to a tagged-union, except that it supports non-POD data types as well. It accomplishes this magic by using a char buffer, placement new/delete, and reinterpret_cast<>.

I recently tried compiling this code under gcc 4.4.3 (with -O3 and -Wall), and got lots of warnings like this:

warning: dereferencing type-punned pointer will break strict-aliasing rules

From what I’ve read, this is an indication that the gcc’s new optimizer might generate ‘buggy’ code, which I obviously would like to avoid.

I’ve pasted a ‘toy version’ of my code below; is there anything I can do to my code to make it safer under gcc 4.4.3, while still supporting non-POD data types? I know that as a last resort I could always compile the code with -fno-strict-aliasing, but it would be nice to have code that doesn’t break under optimization so I’d rather not do that.

(Note that I’d like to avoid introducing a boost or C++0X dependency into the codebase, so while boost/C++0X solutions are interesting, I’d prefer something a little more old-fashioned)

#include <new>

class Duck
{
public:
   Duck() : _speed(0.0f), _quacking(false) {/* empty */}
   virtual ~Duck() {/* empty */}  // virtual only to demonstrate that this may not be a POD type

   float _speed;
   bool _quacking;
};

class Soup
{
public:
   Soup() : _size(0), _temperature(0.0f) {/* empty */}
   virtual ~Soup() {/* empty */}  // virtual only to demonstrate that this may not be a POD type

   int _size;
   float _temperature;
};

enum {
   TYPE_UNSET = 0,
   TYPE_DUCK,
   TYPE_SOUP
};

/** Tagged-union style variant class, can hold either one Duck or one Soup, but not both at once. */
class DuckOrSoup
{
public:
   DuckOrSoup() : _type(TYPE_UNSET) {/* empty*/}
   ~DuckOrSoup() {Unset();}

   void Unset() {ChangeType(TYPE_UNSET);}
   void SetValueDuck(const Duck & duck) {ChangeType(TYPE_DUCK); reinterpret_cast<Duck*>(_data)[0] = duck;}
   void SetValueSoup(const Soup & soup) {ChangeType(TYPE_SOUP); reinterpret_cast<Soup*>(_data)[0] = soup;}

private:
   void ChangeType(int newType);

   template <int S1, int S2> struct _maxx {enum {sz = (S1>S2)?S1:S2};};
   #define compile_time_max(a,b) (_maxx< (a), (b) >::sz)
   enum {STORAGE_SIZE = compile_time_max(sizeof(Duck), sizeof(Soup))};

   char _data[STORAGE_SIZE];
   int _type;   // a TYPE_* indicating what type of data we currently hold
};

void DuckOrSoup :: ChangeType(int newType)
{
   if (newType != _type)
   {
      switch(_type)
      {
         case TYPE_DUCK: (reinterpret_cast<Duck*>(_data))->~Duck(); break;
         case TYPE_SOUP: (reinterpret_cast<Soup*>(_data))->~Soup(); break;
      }
      _type = newType;
      switch(_type)
      {
         case TYPE_DUCK: (void) new (_data) Duck();  break;
         case TYPE_SOUP: (void) new (_data) Soup();  break;
      }
   }
}

int main(int argc, char ** argv)
{
   DuckOrSoup dos;
   dos.SetValueDuck(Duck());
   dos.SetValueSoup(Soup());
   return 0;
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T08:51:15+00:00Added an answer on May 18, 2026 at 8:51 am

    OK, you can do it if you are willing to store an extra void *. I reformatted your sample a bit so it was easier for me to work with. Look at this and see if it fits your needs. Also, note that I provided a few samples so you can add some templates to it that will help usability. They can be extended much more, but that should give you a good idea.

    There is also some output stuff to help you see what is going on.

    One more thing, I assume you know that you need to provide appropriate copy-ctor and assignment-operator but that is not the crux of this problem.

    My g++ version info:

    g++ –version
    g++ (SUSE Linux) 4.5.0 20100604 [gcc-4_5-branch revision 160292]

    #include <new>
    #include <iostream>
    
    class Duck
    {
    public:
       Duck(float s = 0.0f, bool q = false) : _speed(s), _quacking(q)
      {
        std::cout << "Duck::Duck()" << std::endl;
      }
       virtual ~Duck() // virtual only to demonstrate that this may not be a POD type
       {
         std::cout << "Duck::~Duck()" << std::endl;
       }
    
       float _speed;
       bool _quacking;
    };
    
    class Soup
    {
    public:
       Soup(int s = 0, float t = 0.0f) : _size(s), _temperature(t)
      {
        std::cout << "Soup::Soup()" << std::endl;
      }
       virtual ~Soup() // virtual only to demonstrate that this may not be a POD type
       {
         std::cout << "Soup::~Soup()" << std::endl;
       }
    
       int _size;
       float _temperature;
    };
    
    enum TypeEnum {
       TYPE_UNSET = 0,
       TYPE_DUCK,
       TYPE_SOUP
    };
    template < class T > TypeEnum type_enum_for();
    template < > TypeEnum type_enum_for< Duck >() { return TYPE_DUCK; }
    template < > TypeEnum type_enum_for< Soup >() { return TYPE_SOUP; }
    
    /** Tagged-union style variant class, can hold either one Duck or one Soup, but not both at once. */
    class DuckOrSoup
    {
    public:
       DuckOrSoup() : _type(TYPE_UNSET), _data_ptr(_data) {/* empty*/}
       ~DuckOrSoup() {Unset();}
    
       void Unset() {ChangeType(TYPE_UNSET);}
       void SetValueDuck(const Duck & duck)
       {
         ChangeType(TYPE_DUCK);
         reinterpret_cast<Duck*>(_data_ptr)[0] = duck;
       }
       void SetValueSoup(const Soup & soup)
       {
         ChangeType(TYPE_SOUP);
         reinterpret_cast<Soup*>(_data_ptr)[0] = soup;
       }
    
       template < class T >
       void set(T const & t)
       {
         ChangeType(type_enum_for< T >());
         reinterpret_cast< T * >(_data_ptr)[0] = t;
       }
    
       template < class T >
       T & get()
       {
         ChangeType(type_enum_for< T >());
         return reinterpret_cast< T * >(_data_ptr)[0];
       }
    
       template < class T >
       T const & get_const()
       {
         ChangeType(type_enum_for< T >());
         return reinterpret_cast< T const * >(_data_ptr)[0];
       }
    
    private:
       void ChangeType(int newType);
    
       template <int S1, int S2> struct _maxx {enum {sz = (S1>S2)?S1:S2};};
       #define compile_time_max(a,b) (_maxx< (a), (b) >::sz)
       enum {STORAGE_SIZE = compile_time_max(sizeof(Duck), sizeof(Soup))};
    
       char _data[STORAGE_SIZE];
       int _type;   // a TYPE_* indicating what type of data we currently hold
       void * _data_ptr;
    };
    
    void DuckOrSoup :: ChangeType(int newType)
    {
       if (newType != _type)
       {
          switch(_type)
          {
             case TYPE_DUCK: (reinterpret_cast<Duck*>(_data_ptr))->~Duck(); break;
             case TYPE_SOUP: (reinterpret_cast<Soup*>(_data_ptr))->~Soup(); break;
          }
          _type = newType;
          switch(_type)
          {
             case TYPE_DUCK: (void) new (_data) Duck();  break;
             case TYPE_SOUP: (void) new (_data) Soup();  break;
          }
       }
    }
    
    int main(int argc, char ** argv)
    {
       Duck sample_duck; sample_duck._speed = 23.23;
       Soup sample_soup; sample_soup._temperature = 98.6;
       std::cout << "Just saw sample constructors" << std::endl;
       {
         DuckOrSoup dos;
         std::cout << "Setting to Duck" << std::endl;
         dos.SetValueDuck(sample_duck);
         std::cout << "Setting to Soup" << std::endl;
         dos.SetValueSoup(sample_soup);
         std::cout << "Should see DuckOrSoup destruct which will dtor a Soup"
           << std::endl;
       }
       {
         std::cout << "Do it again with the templates" << std::endl;
         DuckOrSoup dos;
         std::cout << "Setting to Duck" << std::endl;
         dos.set(sample_duck);
         std::cout << "duck speed: " << dos.get_const<Duck>()._speed << std::endl;
         std::cout << "Setting to Soup" << std::endl;
         dos.set(sample_soup);
         std::cout << "soup temp: " << dos.get_const<Soup>()._temperature << std::endl;
         std::cout << "Should see DuckOrSoup destruct which will dtor a Soup"
           << std::endl;
       }
       {
         std::cout << "Do it again with only template get" << std::endl;
         DuckOrSoup dos;
         std::cout << "Setting to Duck" << std::endl;
         dos.get<Duck>() = Duck(42.42);
         std::cout << "duck speed: " << dos.get_const<Duck>()._speed << std::endl;
         std::cout << "Setting to Soup" << std::endl;
         dos.get<Soup>() = Soup(0, 32);
         std::cout << "soup temp: " << dos.get_const<Soup>()._temperature << std::endl;
         std::cout << "Should see DuckOrSoup destruct which will dtor a Soup"
           << std::endl;
       }
       std::cout << "Get ready to see sample destructors" << std::endl;
       return 0;
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I've got a string that has curly quotes in it. I'd like to replace
i got an object with contents of html markup in it, for example: string
I have just tried to save a simple *.rtf file with some websites and
link Im having trouble converting the html entites into html characters, (&# 8217;) i
Does anyone know how can I replace this 2 symbol below from the string
I have a JSP page retrieving data and when single or double quotes are
I want to count how many characters a certain string has in PHP, but
Seemingly simple, but I cannot find anything relevant on the web. What is the
this is what i have right now Drawing an RSS feed into the php,
I'm trying to decode HTML entries from here NYTimes.com and I cannot figure out

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.