473,385 Members | 1,587 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Safe union of std::vectors

I'd like to do something along these lines:

struct foo
{
int i1_;
int i2_;
};

struct bar
{
double d1_;
double d2_;
};

typedef std::vector<foo> vectorFoo;
typedef std::vector<bar> vectorBar;

union vectorAll
{
vectorFoo foo_;
vectorBar bar_;
};

static vectorAll myVectorAll;
....
foo myFoo;
myVectorAll.foo_.push_back(myFoo);
myVectorAll.foo_.clear();
....
bar myBar;
myVectorAll.bar_.push_back(myBar);
myVectorAll.bar_.clear();

But a) I'm fairly sure that this isn't valid C++ because std::vector
must have a constructor, b) it seems very unsafe. and c) it precludes
sensible requirements such as clearing myVectorAll without knowing what
type is in it. (Intuitively one might want to be able to do a
myVectorAll.clear());

Given that one of my target compilers is too uncompliant to compile
boost, I can't use boost::any for this. What are my other options?

--
Simon Elliott http://www.ctsn.co.uk
Jul 23 '05 #1
5 8105
"Simon Elliott" <Simon at ctsn.co.uk> wrote in message
news:41***********************@news.gradwell.net.. .
I'd like to do something along these lines:

struct foo
{
int i1_;
int i2_;
};

struct bar
{
double d1_;
double d2_;
};

typedef std::vector<foo> vectorFoo;
typedef std::vector<bar> vectorBar;

union vectorAll
{
vectorFoo foo_;
vectorBar bar_;
};

static vectorAll myVectorAll;
...
foo myFoo;
myVectorAll.foo_.push_back(myFoo);
myVectorAll.foo_.clear();
...
bar myBar;
myVectorAll.bar_.push_back(myBar);
myVectorAll.bar_.clear();

But a) I'm fairly sure that this isn't valid C++ because std::vector
must have a constructor,
It's invalid because std::vector *does* have a (non-trivial)
constructor (as well as other precluded member functions).
(C&V below)
b) it seems very unsafe.
Well, I suppose it you were able to convince a compiler
to create code for it, it would very likely be 'unsafe'. :-)
and c) it precludes
sensible requirements such as
Such as violating the standard's rules. :-)
clearing myVectorAll without knowing what
type is in it. (Intuitively one might want to be able to do a
myVectorAll.clear());
I wouldn't intiut that because the your union has no member
functions.
Given that one of my target compilers is too uncompliant to compile
boost, I can't use boost::any for this. What are my other options?


Don't use a union. :-) How about a function template?
(Of course that's just a guess, without knowing more
about what you're trying to do.)

ISO/IEC 14882:1998(E)

9.5 Unions

1 In a union, at most one of the data members can be active
at any time, that is, the value of at most one of the data
members can be stored in a union at any time. [Note: one
special guarantee is made in order to simplify the use of
unions: If a POD*-union contains several POD*-structs that
share a common initial sequence (9.2), and if an object of
this POD*-union type contains one of the POD*-structs, it is
permitted to inspect the common initial sequence of any of
POD*struct members; see 9.2. ] The size of a union is suffi*-
cient to contain the largest of its data members. Each data
member is allocated as if it were the sole member of a struct.
A union can have member functions (including constructors
and destructors), but not virtual (10.3) functions. A union
shall not have base classes. A union shall not be used as a
base class. An object of a class with a non*-trivial constructor
(12.1), a non-*trivial copy constructor (12.8), a non*-trivial
destructor (12.4), or a non-*trivial copy assignment operator
(13.5.3, 12.8) cannot be a member of a union, nor can an
array of such objects. If a union contains a static data
member, or a member of reference type, the program is ill-*formed.
-Mike
Jul 23 '05 #2

Simon Elliott wrote:
I'd like to do something along these lines:

struct foo {...}
struct bar {...}
typedef std::vector<foo> vectorFoo;
typedef std::vector<bar> vectorBar;

union vectorAll
{
vectorFoo foo_;
vectorBar bar_;
};

static vectorAll myVectorAll;
...
foo myFoo;
myVectorAll.foo_.push_back(myFoo);
myVectorAll.foo_.clear();
...
bar myBar;
myVectorAll.bar_.push_back(myBar);
myVectorAll.bar_.clear();

But a) I'm fairly sure that this isn't valid C++ because std::vector
must have a constructor, b) it seems very unsafe. and c) it precludes
sensible requirements such as clearing myVectorAll without knowing what type is in it. (Intuitively one might want to be able to do a
myVectorAll.clear());

Given that one of my target compilers is too uncompliant to compile
boost, I can't use boost::any for this. What are my other options?


The logical solution is probably to wrap your own vector class
around a union of two pointers, a Foo* and a Bar*. You can use a
shared size member, so you can implement empty() without
differentiating which elements there aren't ;) For most operations
you will have to use a tag, though.

You'd have to add your own push_back overloads, your own iterators,
a foo_begin() and a bar_begin() but it's not too difficult.

BTW, if you're targetting multiple platforms and one is very out
of date, you might want to consider Comeau.

HTH,
Michiel Salters

Jul 23 '05 #3
Simon Elliott wrote:
I'd like to do something along these lines:

struct foo
{
int i1_;
int i2_;
};

struct bar
{
double d1_;
double d2_;
};

typedef std::vector<foo> vectorFoo;
typedef std::vector<bar> vectorBar;

union vectorAll
{
vectorFoo foo_;
vectorBar bar_;
};

static vectorAll myVectorAll;
...
foo myFoo;
myVectorAll.foo_.push_back(myFoo);
myVectorAll.foo_.clear();
...
bar myBar;
myVectorAll.bar_.push_back(myBar);
myVectorAll.bar_.clear();

[...]
Given that one of my target compilers is too uncompliant to compile
boost, I can't use boost::any for this. What are my other options?


Perhaps something like the following might do the job:

class FooBarVector
{
enum VectorType { NONE, FOO, BAR };
public:
FooBarVector() : type_(NONE) { };

~FooBarVector() {
switch(type_) {
case FOO: delete v_.foo_; break;
case BAR: delete v_.bar_; break;
}
type_ = NONE;
}

vectorFoo& foo(){
if (type_ == BAR)
delete v_.bar_;
if (type_ != FOO) {
v_.foo_ = new vectorFoo();
type_ = FOO;
}
return *(v_.foo_);
}

vectorBar& bar(){
if (type_ == FOO)
delete v_.foo_;
if (type_ != BAR) {
v_.bar_ = new vectorBar();
type_ = BAR;
}
return *(v_.bar_);
}
private:
union {
vectorFoo *foo_;
vectorBar *bar_;
} v_;

VectorType type_;
};

// ...
static FooBarVector v;
// ...
Foo myFoo;
v.foo().push_back(myFoo);
v.foo().clear();
// ...
Bar myBar;
v.bar().push_back(myBar);
v.bar().clear();
// ...

As an alternative, you can throw an exception, if foo() is called with
an non-empty bar-Vector (and vice versa).

greetings
Martin
Jul 23 '05 #4
On 02/02/2005, msalters wrote:
The logical solution is probably to wrap your own vector class
around a union of two pointers, a Foo* and a Bar*. You can use a
shared size member, so you can implement empty() without
differentiating which elements there aren't ;) For most operations
you will have to use a tag, though.

You'd have to add your own push_back overloads, your own iterators,
a foo_begin() and a bar_begin() but it's not too difficult.
Yes. I was hoping for a solution that didn't involve vectors of
pointers though.
BTW, if you're targetting multiple platforms and one is very out
of date, you might want to consider Comeau.


I'd like to drop support for BCB3 but can't at the moment. I'm quite
interested in adding Comeau to the list of supported compilers at some
point.

--
Simon Elliott http://www.ctsn.co.uk
Jul 23 '05 #5

Simon Elliott wrote:
On 02/02/2005, msalters wrote:
The logical solution is probably to wrap your own vector class
around a union of two pointers, a Foo* and a Bar*. You can use a
shared size member, so you can implement empty() without
differentiating which elements there aren't ;) For most operations
you will have to use a tag, though.

You'd have to add your own push_back overloads, your own iterators,
a foo_begin() and a bar_begin() but it's not too difficult.
Yes. I was hoping for a solution that didn't involve vectors of
pointers though.


It's not a vector of pointers, just

template< typename T1, typename T2 >
class bi_vector
{
union {
T1* t1_array;
T2* t2_array;
} data;
size_t size;
enum { t1_used, t2_used } type_in_data;
public:
// ...
};
If you want to save memory, you could use a signed integer type
for size, with size > 0 meaning size T1 objects and size < 0
meaning -size T2 objects. Not worth the price if these vectors
are rare, of course.

HTH,
Michiel Salters
BTW, if you're targetting multiple platforms and one is very out
of date, you might want to consider Comeau.


I'd like to drop support for BCB3 but can't at the moment. I'm quite
interested in adding Comeau to the list of supported compilers at

some point.

--
Simon Elliott http://www.ctsn.co.uk


Jul 23 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: ree | last post by:
Unlike arrays I am having problems accessing objects placed in a vector I have a vector of objects called Semesters Each Semester has its own vector of Subjects. I am having problems...
5
by: Pratyush | last post by:
Hi, Suppose there is a vector of objects of class A, i.e., std::vector<A> vec_A(N); The class A satisifies all the STL vector requirements. Now I wish to add some attributes for each of the...
7
by: Jerry Krinock | last post by:
I've declared a class that has some std::vector data members like this: class MyClass { public: ... std::vector<Apples> apples ; ... private: ...
7
by: Martin Magnusson | last post by:
I'm having trouble clearing and resizing a static std::vector of std::vectors (segmentation fault). Is it OK to call clear() and resize() on a static attribute? My code is similar to the one posted...
21
by: Peter Olcott | last post by:
I got the previous alias to std::vector working, and found that it takes up the space of a pointer. I want to find a way to do an alias to a std::vector that does not take up any space. Is there...
7
by: Marcus Kwok | last post by:
I am utilizing a std::vector<int>, but due to a platform-specific reason (Managed C++, but this is irrelevant), in order to include it as a member of a class, I have to work with a pointer to it. ...
5
by: arnuld | last post by:
/* C++ Primer 4/e * STATEMENT * given 2 vectors of integers, write a programme to determine whether one vector * is the prefix of the other vector e.g. if 1st vector has elements...
8
by: Bryan | last post by:
Hello all. I'm fairly new to c++. I've written several programs using std::vectors, and they've always worked just fine. Until today. The following is a snippet of my code (sorry, can't...
3
by: Carter | last post by:
I am currently writing some code where I have a list of objects with a maximum occupancy of 4. I have been employing std::vector for this but I was wondering how much overhead is involved. Is it...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.