Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Making a std::string a member of a union ???

Reply
Thread Tools

Making a std::string a member of a union ???

 
 
Simon G Best
Guest
Posts: n/a
 
      01-09-2007
Peter Olcott wrote:
>
> So it looks like you are saying that Simple() invokes something() therefore
> simple does something and I am wrong that Simple(){} is empty of semantics.


Yep

--
Simon G Best
What happens if I mention Leader Kibo in my .signature?
 
Reply With Quote
 
 
 
 
BobR
Guest
Posts: n/a
 
      01-09-2007

Peter Olcott wrote in message <1qQoh.48816$(E-Mail Removed)>...
>
>"Andre Kostur" <(E-Mail Removed)> wrote in message ...
>> You can't do this even with your own string:
>> Section 12.1.11: "A union member shall not be of a class type (or array
>> thereof) that has a non-trivial constructor.".

>
>If I create my own StringType class that has every other feature of

std::string,
>except nontrivial constructors, then it should work?
>For example if every instance of StringType is always empty unless data is
>explicitly added using operator=() or other means, then there would seem to

be
>no need for constructors.


Storage? What good is a String class that can't store anything?

Do you understand what a union is?

std::cout<<" sizeof(std::string) ="
<<sizeof(std::string)<<std::endl;
std::cout<<" sizeof(double) ="
<<sizeof(double)<<std::endl;
// out: sizeof(std::string) =4
// out: sizeof(double) =8

So, if you did (if it compiled):

union AnyType {
std::string String;
double Number;
};

.... the union would be the size of a double (since it is bigger than
std::string (on my machine)).

Try it this way:

#include <iostream> // #include <ostream>
#include <string>

union AnyType {
std::string *String; // pointer
double Number;
};

int main(){
AnyType AnyT;
std::string Sting("AnyType AnyT;");
AnyT.String = &Sting;
std::cout<<" AnyT.String ="<<*(AnyT.String)<<std::endl;
AnyT.Number = 543.123;
std::cout<<" AnyT.Number ="<<AnyT.Number<<std::endl;
// oops! // std::cout<<" AnyT.String ="<<*(AnyT.String)<<std::endl;
return 0;
} // main()

But, the union still doesn't seem logical to me.
--
Bob R
POVrookie


 
Reply With Quote
 
 
 
 
Peter Olcott
Guest
Posts: n/a
 
      01-09-2007

"Ron Natalie" <(E-Mail Removed)> wrote in message
news:45a4062f$0$28093$(E-Mail Removed) m...
> Peter Olcott wrote:
>> "Ron Natalie" <(E-Mail Removed)> wrote in message
>> news:45a403f2$0$28100$(E-Mail Removed) m...
>>> Peter Olcott wrote:
>>>
>>>> If all that I want is std::string could I simply use [ std::string*
>>>> String ] in my union?
>>> You would need management code to allocate and deallocate it.

>>
>> I already figured that, are there any other issues?

> You need to remember which element you stored in the vector.
>
> Once you do all that you probably have reimplemented boost::any.


Okay then this is the way that I will do it.


 
Reply With Quote
 
Michael DOUBEZ
Guest
Posts: n/a
 
      01-10-2007
Peter Olcott a écrit :
> Is there anyway of doing this besides making my own string from scratch?
>
> union AnyType {
> std::string String;
> double Number;
> };


Use pointer instead.
union AnyType
{
std::string* str;
double number;
};
And don't forget to delete it before writing into the
structure(embedding that in a structure with accessor).

Or use boost::variant or boost::any as Thomas J. Gritzan wrote.

Michael
 
Reply With Quote
 
Peter Olcott
Guest
Posts: n/a
 
      01-10-2007

"Michael DOUBEZ" <(E-Mail Removed)> wrote in message
news:45a4710f$0$3324$(E-Mail Removed)...
> Peter Olcott a écrit :
>> Is there anyway of doing this besides making my own string from scratch?
>>
>> union AnyType {
>> std::string String;
>> double Number;
>> };

>
> Use pointer instead.
> union AnyType
> {
> std::string* str;
> double number;
> };



> And don't forget to delete it before writing into the structure(embedding that
> in a structure with accessor).


I don't know what you mean by this.


>
> Or use boost::variant or boost::any as Thomas J. Gritzan wrote.
>
> Michael



 
Reply With Quote
 
Jim Langston
Guest
Posts: n/a
 
      01-10-2007
"Peter Olcott" <(E-Mail Removed)> wrote in message
news5Uoh.22778$(E-Mail Removed)...
>
> "Ron Natalie" <(E-Mail Removed)> wrote in message
> news:45a4062f$0$28093$(E-Mail Removed) m...
>> Peter Olcott wrote:
>>> "Ron Natalie" <(E-Mail Removed)> wrote in message
>>> news:45a403f2$0$28100$(E-Mail Removed) m...
>>>> Peter Olcott wrote:
>>>>
>>>>> If all that I want is std::string could I simply use [ std::string*
>>>>> String ] in my union?
>>>> You would need management code to allocate and deallocate it.
>>>
>>> I already figured that, are there any other issues?

>> You need to remember which element you stored in the vector.
>>
>> Once you do all that you probably have reimplemented boost::any.

>
> Okay then this is the way that I will do it.


It depends on what you are actually tryign to do. A union of a double and a
pointer doesn't seem like it will do you any good. It sounds more like you
want to refer to this double as either a double, or as a std::string,
correct? It would seem a simple class would work for you. Something like:

#include <iostream>
#include <string>
#include <sstream>

class AnyType
{
public:
operator double() const { return Val_; }
operator std::string () const
{
std::stringstream Convert;
Convert << Val_;
return Convert.str();
}
AnyType* operator= ( const double Val ) { Val_ = Val; return this; }
AnyType* operator= ( const std::string& Val )
{
std::stringstream Convert;
Convert << Val;
Convert >> Val_;
return this;
}
private:
double Val_;
};

int main()
{
AnyType MyDouble;
MyDouble = 1234.56;
std::cout << MyDouble << "\n";
MyDouble = "2345.67";
std::cout << MyDouble << "\n";

std::string wait;
std::getline( std::cin, wait );
}

This could easily be converted to a template for any type.

Is this the kind of thing you are looking for?


 
Reply With Quote
 
Michael DOUBEZ
Guest
Posts: n/a
 
      01-10-2007
Peter Olcott a écrit :
> "Michael DOUBEZ" <(E-Mail Removed)> wrote in message
> news:45a4710f$0$3324$(E-Mail Removed)...
>> Peter Olcott a écrit :
>>> Is there anyway of doing this besides making my own string from scratch?
>>>
>>> union AnyType {
>>> std::string String;
>>> double Number;
>>> };

>> Use pointer instead.
>> union AnyType
>> {
>> std::string* str;
>> double number;
>> };

>
>
>> And don't forget to delete it before writing into the structure(embedding that
>> in a structure with accessor).

>
> I don't know what you mean by this.


I dont pretend it is good C++ design but it looks like what you ask for.

Accessor solution is something like this (not tested):
struct GenericContent
{
public:
//! supported types
enum mytype{ type_none, type_str, type_number };

//constructor - destructor
GenericContent():_type(type_none){}
~GenericContent()
{ //clean internal data
this->clean_me();
}
//! setters
void setString(const std::string& str)
{ //clean internal data
this->clean_me();
this->_type=type_str;
this->_data.str=new std::string(str);
}
void setNumber(double num)
{ //clean internal data
this->clean_me();
this->_type=type_number;
this->_data.number=num;
}

//! accessors
mytype getType()const
{
return this->_type;
}
const string& getString()const
{
assert(this->_type==type_str);
return *(this->_data.str);
}
double getNumber()const
{
assert(this->_type==type_number);
return this->_data.number;
}
private:
//! clean internal data and reset to none
void clean_me()
{
if(this->_type==type_str)
{
delete this->_data.str;
}
this->_type=type_none;
}

//! refuse copy ...
GenericContent(const GenericContent&);
GenericContent& operator=(const GenericContent& genc);

private:
//! store real content of data
mytype _type;
//! data
union
{
std::string* str;
double number;
} _data;
};

 
Reply With Quote
 
Peter Olcott
Guest
Posts: n/a
 
      01-10-2007
I can't tell what you are trying to do here, but, the std::string will probably
not hold data that can be converted to and from string.

"Jim Langston" <(E-Mail Removed)> wrote in message
news:Hk%oh.284$(E-Mail Removed)...
> "Peter Olcott" <(E-Mail Removed)> wrote in message
> news5Uoh.22778$(E-Mail Removed)...
>>
>> "Ron Natalie" <(E-Mail Removed)> wrote in message
>> news:45a4062f$0$28093$(E-Mail Removed) m...
>>> Peter Olcott wrote:
>>>> "Ron Natalie" <(E-Mail Removed)> wrote in message
>>>> news:45a403f2$0$28100$(E-Mail Removed) m...
>>>>> Peter Olcott wrote:
>>>>>
>>>>>> If all that I want is std::string could I simply use [ std::string*
>>>>>> String ] in my union?
>>>>> You would need management code to allocate and deallocate it.
>>>>
>>>> I already figured that, are there any other issues?
>>> You need to remember which element you stored in the vector.
>>>
>>> Once you do all that you probably have reimplemented boost::any.

>>
>> Okay then this is the way that I will do it.

>
> It depends on what you are actually tryign to do. A union of a double and a
> pointer doesn't seem like it will do you any good. It sounds more like you
> want to refer to this double as either a double, or as a std::string, correct?
> It would seem a simple class would work for you. Something like:
>
> #include <iostream>
> #include <string>
> #include <sstream>
>
> class AnyType
> {
> public:
> operator double() const { return Val_; }
> operator std::string () const
> {
> std::stringstream Convert;
> Convert << Val_;
> return Convert.str();
> }
> AnyType* operator= ( const double Val ) { Val_ = Val; return this; }
> AnyType* operator= ( const std::string& Val )
> {
> std::stringstream Convert;
> Convert << Val;
> Convert >> Val_;
> return this;
> }
> private:
> double Val_;
> };
>
> int main()
> {
> AnyType MyDouble;
> MyDouble = 1234.56;
> std::cout << MyDouble << "\n";
> MyDouble = "2345.67";
> std::cout << MyDouble << "\n";
>
> std::string wait;
> std::getline( std::cin, wait );
> }
>
> This could easily be converted to a template for any type.
>
> Is this the kind of thing you are looking for?
>



 
Reply With Quote
 
Sylvester Hesp
Guest
Posts: n/a
 
      01-10-2007
"Peter Olcott" <(E-Mail Removed)> wrote in message
news:ZtPoh.8718$(E-Mail Removed)...
> Is there anyway of doing this besides making my own string from scratch?
>
> union AnyType {
> std::string String;
> double Number;
> };
>


If you really want to union the memory footprint of types with non-trivial
constructors, you could wrap them in a container which has a trivial
constructor. Unfortunately, this will currently not yield very portable code
as you won't have any control over alignment, but it will probably work on
most platforms:

#include <string>

template<class T> class UnionMember
{
public:
void construct()
{ new (*this) T(); }
template<class P1> void construct (const P1 & p1)
{ new (*this) T(p1); }
template<class P1, class P2> void construct (const P1 & p1, const P2 &
p2)
{ new (*this) T(p1, p2); }
// etc.

void destroy() { (*this)->~T(); }

operator T * () { return reinterpret_cast<T*>(m_data); }
operator const T * () const { return reinterpret_cast<const
T*>(m_data); }

T * operator -> () { return operator T*(); }
const T * operator -> () const { return operator const T*(); }

private:
char m_data[sizeof(T)]; // for true portable code you'll need to align
this buffer to meet the alignment requirements for T.
};

union MyUnion
{
UnionMember<std::string> myString;
double myDouble;
};

int main()
{
MyUnion u;

// construct a string within the union
u.myString.construct("hi there");

// assign it with a different string
*u.myString = "goodbye";

// assign the double - don't forget to destroy the string first!
u.myString.destroy(); // destroy the string
u.myDouble = 34.5; // and assign the double.
}

You should take care to construct every object on it's first use and
destruct it before using another value in the union, or when you dispose of
the union.

The next C++ standard revision will most probably include methods of
retrieving and controlling alignment of datamembers.

- Sylvester


 
Reply With Quote
 
Jim Langston
Guest
Posts: n/a
 
      01-10-2007
> "Jim Langston" <(E-Mail Removed)> wrote in message
> news:Hk%oh.284$(E-Mail Removed)...
>> "Peter Olcott" <(E-Mail Removed)> wrote in message
>> news5Uoh.22778$(E-Mail Removed)...
>>>
>>> "Ron Natalie" <(E-Mail Removed)> wrote in message
>>> news:45a4062f$0$28093$(E-Mail Removed) m...
>>>> Peter Olcott wrote:
>>>>> "Ron Natalie" <(E-Mail Removed)> wrote in message
>>>>> news:45a403f2$0$28100$(E-Mail Removed) m...
>>>>>> Peter Olcott wrote:
>>>>>>
>>>>>>> If all that I want is std::string could I simply use [ std::string*
>>>>>>> String ] in my union?
>>>>>> You would need management code to allocate and deallocate it.
>>>>>
>>>>> I already figured that, are there any other issues?
>>>> You need to remember which element you stored in the vector.
>>>>
>>>> Once you do all that you probably have reimplemented boost::any.
>>>
>>> Okay then this is the way that I will do it.

>>
>> It depends on what you are actually tryign to do. A union of a double
>> and a pointer doesn't seem like it will do you any good. It sounds more
>> like you want to refer to this double as either a double, or as a
>> std::string, correct? It would seem a simple class would work for you.
>> Something like:
>>
>> #include <iostream>
>> #include <string>
>> #include <sstream>
>>
>> class AnyType
>> {
>> public:
>> operator double() const { return Val_; }
>> operator std::string () const
>> {
>> std::stringstream Convert;
>> Convert << Val_;
>> return Convert.str();
>> }
>> AnyType* operator= ( const double Val ) { Val_ = Val; return this; }
>> AnyType* operator= ( const std::string& Val )
>> {
>> std::stringstream Convert;
>> Convert << Val;
>> Convert >> Val_;
>> return this;
>> }
>> private:
>> double Val_;
>> };
>>
>> int main()
>> {
>> AnyType MyDouble;
>> MyDouble = 1234.56;
>> std::cout << MyDouble << "\n";
>> MyDouble = "2345.67";
>> std::cout << MyDouble << "\n";
>>
>> std::string wait;
>> std::getline( std::cin, wait );
>> }
>>
>> This could easily be converted to a template for any type.
>>
>> Is this the kind of thing you are looking for?


"Peter Olcott" <(E-Mail Removed)> wrote in message
news:mZ5ph.1264$(E-Mail Removed)...
>I can't tell what you are trying to do here, but, the std::string will
>probably not hold data that can be converted to and from string.


Please don't top post. Message rearranged.

You mean not hold data that can be converted to and from a double?

Okay, so you want your union to hold *either* a std::string or a double.
There are a few ways to do this including templates, templates with common
base class, pointers, etc...

How is it you want to be able to use AnyType?




 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Multiple union member initialization Ricky Lung C++ 5 08-19-2004 09:07 AM
union in struct without union name Peter Dunker C Programming 2 04-26-2004 07:23 PM
map XML union to C union (and vice-versa) Matt Garman XML 1 04-25-2004 12:40 AM
How would I use qsort to sort a struct with a char* member and a long member - I want to sort in order of the long member Angus Comber C Programming 7 02-05-2004 06:41 PM
Setting union member in structure Jeff Massung C++ 2 12-22-2003 05:53 PM



Advertisments